- 1. 你为什么要看这篇Artikel
- 2. 总览对比表
- 3. FreeModbus —— Eingebettet裸机的标准答案
- 4. libmodbus —— Linux Arbeitskontrolle机的不二之选
- 5. pymodbus —— Python 生态的事实标准
- 6. NModbus —— .NET 平台的唯一严肃Auswahl
- 7. jamod —— Java 生态的「前辈」,但建议你别用
- 8. modbus-tk —— 快速原型的好帮手
- 9. QtModbus —— Qt Entwickler的原生方案
- 10. 新手推荐路径
- 11. 经典组合方案
- 12. 避坑清单
- 13. 选型决策速查
你为什么要看这篇Artikel
这个问题在 Stack Overflow、control.com、CSDN 上被问了几千次——「我该用哪个开源 Modbus 库?」。每次回答都是零散的几句,没人Das System对比过。中文社区更惨,搜出来的帖子一半在贴十Jahr前 NModbus4 的代码,连 NModbus 主仓库已经迁移zu 3.0.x 了都不知道。
我花了三天Zeit把这七个Vereinbarung栈的仓库翻了一遍,跑了每个的最小Beispiel,Bestätigen了维护Status。下面是Ergebnis。如果你赶Zeit,直接跳zu「新手推荐路径」那一段,选你的平台对应的库,开工。
总览对比表
| Vereinbarung栈 | 语言 | 许可 | Star 数 | 维护Status | Hauptstation | Von der Station | RTU | TCP | 适合谁 |
|---|---|---|---|---|---|---|---|---|---|
| FreeModbus | C | BSD | ~1.5k | 低活跃 | 付费 | ✅ | ✅ | ✅ | STM32 裸机/RTOS |
| libmodbus | C | LGPL v2.1+ | ~3.5k | 活跃 | ✅ | ✅ | ✅ | ✅ | Linux Arbeitskontrolle机/网关 |
| pymodbus | Python | BSD | ~2.2k | 非常活跃 | ✅ | ✅ | ✅ | ✅ | 上位机/测试Drehbuch |
| NModbus | C# | MIT | ~700 | 活跃 | ✅ | ✅ | ✅ | ✅ | .NET/WinForm 上位机 |
| jamod | Java | Apache 2.0 | ~300 | 停滞 | ✅ | ✅ | ✅ | ✅ | Java 遗留Das System |
| modbus-tk | Python | LGPL | ~500 | 低活跃 | ✅ | ✅ | ✅ | ✅ | 快速原型 |
| QtModbus | C++ | LGPL/GPL | Qt 内置 | 活跃 | ✅ | ✅ | ❌ | ✅ | Qt 跨平台应用 |
Star 数是我在 2026 Jahr 6 月抓的,大致Anzahl级对,具体数字你去 GitHub 看一眼就知道。
FreeModbus —— Eingebettet裸机的标准答案
GitHub: https://github.com/cwalter-at/freemodbus
FreeModbus 是 Christian Walter 写的,一个奥地利Eingebettet工程师。这东西在 STM32 圈子里的地位相当于 Linux 内核里的 ext4——你不是不能用别的,但用它是最不会出错的。
**代码体积**:编译完大约 6-12KB ROM,取决于你开了哪些Funktionscode和传输模式。RAM 开销几百Bytes,主要是那几块Daten缓冲区和Ereignisse队列。基本上是个 Cortex-M0 就能跑。
**Funktionscode支持**:03(Lesen Sie das Register)、04(Eingangsregister lesen)、06(Schreiben eines einzelnen Registers)、16(Schreiben mehrerer Register)、01(读线圈)、02(Lesen Sie getrennte Eingabe)、05(Schreiben Sie eine einzelne Schleife.)、15(Schreiben Sie mehrere Schleife.)。还有 17(报告Von der Station ID)。注意,没有 22(掩码写Register.)和 23(Lesen Sie mehrere Register),需要的话得自己加。
**传输模式**:RTU、ASCII、TCP 都支持,通过编译宏Schalter!。
**Hauptstation/Von der Station**:这是 FreeModbus 最容易被误解的地方。官方仓库只开源了Von der Station代码,Hauptstation是付费的。GitHub 上有不少社区魔改版加了HauptstationFunktion,比如 armink 的 FreeModbus_Slave-Master-RTT-STM32,开源的,质Quantität不错,但不是官方维护。用这些Die三方版本的时候注意:超时处理和重试逻辑实现得很粗糙,别直接上生产。
**Beispiel Code**——STM32 上初始化一个 RTU Von der Station,Adresse 1,Porter Rate 9600,无Prüfungen:
#include "mb.h"
int main(void) {
eMBInit(MB_RTU, 0x01, 0, 9600, MB_PAR_NONE);
eMBEnable();
while (1) {
eMBPoll();
}
}
就这三行。`eMBPoll()` 里跑着整个Vereinbarung栈的Status机,非阻塞的,你需要在定时器中断里喂 3.5T 超时信Nr.给它。这个 3.5T 定时器是 FreeModbus 移植的头Nr.坑,下面会专门讲。
**已知问题**: – 官方仓库更新极慢,最后的大版本 v1.6 已经好几Jahr没动了,bug 修不修看缘Unterteilung – 只支持单Die Serie,一个Vereinbarung栈实例只能绑定一个 UART,多Die SerieSzene要改代码 – TCP 模式用的是 lwIP raw API,不是 socket,这意味着 FreeRTOS+LWIP 环境下能用,但 Linux 上根本跑不了 TCP 模式 – 没有浮点数处理辅助函数,大小端转换自己写
**Dokumentation**:只有一份 API Dokumentation,HTML Das Format的,够用但谈不上好。中文社区Unterricht倒是多,CSDN 搜一下一堆。
libmodbus —— Linux Arbeitskontrolle机的不二之选
GitHub: https://github.com/stephane/libmodbus
维护者 Stéphane Raimbault,法国人。libmodbus 是 C 语言写的最成熟的 Modbus 库,没有之一。3.5k star 不是白来的。
这个库的设计思路跟 FreeModbus 完全不同。FreeModbus 是为资源受限的 MCU 设计的,用回调函数和Status机。libmodbus 是 POSIX 风格的,阻塞 API,`modbus_read_registers()` 调用会一直等zuDaten回来或超时。写Arbeitskontrolle机程序的人喜欢这种风格——简单直接,不用管什么Status机。
**Funktionscode支持**:几乎所有。01/02/03/04/05/06/07/0F/10/11/16/17,还支持 22(掩码写)和 23(读写多个)。有 `modbus_set_float()` / `modbus_get_float()` 可以直接按 IEEE 754 处理浮点数,支持 ABCD/DCBA/BADC/CDAB 四种Befehlseite。
**传输模式**:RTU + TCP 全支持。同一套 API,`modbus_new_rtu()` 创建Die Serie上下文,`modbus_new_tcp()` 创建 TCP 上下文,之后读写Schnittstelle完全一样。
**Hauptstation/Von der Station**:都支持。TCP Von der Station用 `modbus_tcp_listen()` + `modbus_tcp_accept()`,和写 Linux socket 服务端一个套路。
**Beispiel Code**——读Von der Station 1 的保持Register. 0x0000,返回 1 个 16 位值:
#include <modbus.h>
#include <stdio.h>
int main() {
modbus_t *ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);
modbus_set_slave(ctx, 1);
modbus_connect(ctx);
uint16_t val;
modbus_read_registers(ctx, 0, 1, &val);
printf("Register 0 = %dn", val);
modbus_close(ctx);
modbus_free(ctx);
}
**已知问题**: – `modbus_connect()` 的语义容易踩坑。RTU 模式下调的是 `open()` Öffnen Sie die Serie.,TCP 模式下调的是 `connect()` 连Der Server。TCP Von der Station模式不需要也不能调 `modbus_connect()`,而是用 `modbus_tcp_listen()`。搞混了连不上还不知道为什么 – `modbus_free()` 之后指针不会自动置空。如果你在循环里重连,先 free 再 new,不手动 `ctx = NULL` 的话,偶尔会指向已释放的内存,表现为随机崩溃或疯狂重连。这个我吃过亏 – 线程不安全。一个 `modbus_t*` 上下文不能被两个线程同时Operationen,得自己加锁 – Windows 下Die Serie名是 `\\.\COM10` 这种Das Format,Linux 是 `/dev/ttyUSB0`,跨平台编译要注意
**Dokumentation**:官网 libmodbus.org 有一套 manual page 风格的Dokumentation,外加 mkdocs 在线版。清晰但没什么Beispiel项目,就 `tests/` 目录下那几个。
pymodbus —— Python 生态的事实标准
GitHub: https://github.com/pymodbus-dev/pymodbus
pymodbus 是目前维护最活跃的 Modbus 库,没有之一。pymodbus-dev 组织接手后,3.x 重写了Asynchron架构,支持 asyncio,还在持续发版。2024 Jahr底最新的稳定版是 v3.6.x。
**Funktionscode**:全支持。01/02/03/04/05/06/15/16/22/23,连 43(读Ausrüstung识别)都有。
**传输模式**:RTU + TCP + TLS。TLS 支持是 pymodbus 3.x 新加的,可以直接跑 `modbus+tls://`。ASCII 模式也支持但在 3.x 里被标记为废弃。
**Hauptstation/Von der Station**:都支持,而且支持同步和Asynchron两种 API。Von der Station可以跑一个vollständig的模拟器——`pymodbus.simulator` 能从 JSON 配置文件启动一个带多块Register.的虚拟Ausrüstung,上位机开发Tests的时候非常好用。
**Beispiel Code**——同步模式读一个保持Register.:
from pymodbus.client import ModbusSerialClient
client = ModbusSerialClient(port="/dev/ttyUSB0", baudrate=9600)
client.connect()
rr = client.read_holding_registers(address=0, count=1, slave=1)
print(rr.registers[0])
client.close()
Asynchron版稍微多几行,用 `async with` 上下文管理器,配合 asyncio 跑。
**已知问题**: – 2.x zu 3.x 的 API 变化巨大。`pymodbus.client.sync.ModbusSerialClient` 变成了 `pymodbus.client.ModbusSerialClient`,`read_holding_registers` 返回值从 `ReadHoldingRegistersResponse` 变成了 `ModbusResponse`。如果你在网上搜zu的Beispiel代码用的是 `from pymodbus.client.sync import …`,那肯定是 2.x 的,别直接抄 – 同步模式和Asynchron模式不能混用。同一个进程里如果已经跑了 asyncio event loop,同步客户端会阻塞Ereignisse循环导致超时 – RTU 模式下Die Serie超时配置比较敏感。默认的 3 秒超时对于低速Ausrüstung(4800bps)可能不够,需要自己调zu 5-10 秒 – pip 安装时 `pip install pymodbus`,不是 `pymodbus3` 或 `pymodbus2`,别装错了
**Dokumentation**:readthedocs 上有vollständig的Dokumentation,`examples/` 目录下有几十个BeispielDrehbuch。没有中文Dokumentation,但英文很清晰。
NModbus —— .NET 平台的唯一严肃Auswahl
GitHub: https://github.com/NModbus/NModbus
NModbus 的历史有点绕。最早的 NModbus 是 Google Code 上(对,就是那个 Google Code)的一个项目,后来迁移zu GitHub 变成 NModbus4,再后来 NModbus4 也停更了。现在的 NModbus/NModbus 是 NModbus4 的继任者,维护者 rquackenbush,活跃开发中,nuget 包名 `NModbus`,最新版 3.0.x,支持 .NET 6+。
**Funktionscode**:01/02/03/04/05/06/15/16 全支持。22 和 23 需要Custom definiertFunktionscode处理。
**传输模式**:RTU、ASCII、TCP、UDP 全支持。Die Serie通过 `NModbus.Serial` 包,支持 Windows/Linux。
**Hauptstation/Von der Station**:都支持。Von der Station支持Custom definiertDaten存储,可以把Registerabbildungzu内存、Daten库甚至 PLC。
**Beispiel Code**——TCP Hauptstation读一ein Register.:
using NModbus;
var client = new TcpClient("192.168.1.100", 502);
var factory = new ModbusFactory();
var master = factory.CreateMaster(client);
ushort[] result = master.ReadHoldingRegisters(1, 0, 1);
Console.WriteLine(result[0]);
**已知问题**: – Die Serie支持依赖 `System.IO.Ports`,Linux 上需要额外配置权限 – `SlaveDataStore` 在多线程下不是线程安全的,高并发读写时要自己加锁 – Asynchron API(`ReadHoldingRegistersAsync`)返回 `Task`,但底层 I/O 实际上是同步的,没有真正的 async I/O
**Dokumentation**:README 够用,`Samples/` 目录有几个Beispiel。主要靠 Stack Overflow 上的老帖子。
jamod —— Java 生态的「前辈」,但建议你别用
SourceForge: https://sourceforge.net/projects/jamod/ GitHub (openHAB fork): https://github.com/openhab/jamod
jamod 是 Dieter Wimberger 在 2002 Jahr写的,比在座很多工程师的工龄都长。最后一次实质性更新是 2010 Jahr,之后基本就没有了。openHAB 社区 fork 了一个版本修了几个 bug 给自己用,但那个 fork 也只是被动维护。
如果你现在新开一个 Java 项目要做 Modbus,直接跳过 jamod,看 j2mod(GitHub: steveohara/j2mod)。j2mod 是 jamod 的重写版本,Apache 2.0 许可,Java 8+,还在更新(2024 Jahr 7 月最后一次提交),RTU + TCP 全支持,HauptstationVon der Station都有。
但既然这篇Artikel要覆盖 jamod,我还是写上。jamod 支持的Funktionscode:01/02/03/04/05/06/15/16。传输模式 RTU + ASCII + TCP。Serielle Kommunikation依赖 `javax.comm`(巨古老的 API,JDK 都不自带了),替代方案是 RXTX 或 jSerialComm。
Beispiel Code:
import net.wimpi.modbus.Modbus;
import net.wimpi.modbus.io.ModbusTCPTransaction;
import net.wimpi.modbus.msg.ReadInputRegistersRequest;
import net.wimpi.modbus.msg.ReadInputRegistersResponse;
import net.wimpi.modbus.net.TCPMasterConnection;
import java.net.InetAddress;
TCPMasterConnection conn = new TCPMasterConnection(
InetAddress.getByName("192.168.1.100"));
conn.connect();
ReadInputRegistersRequest req = new ReadInputRegistersRequest(0, 1);
ModbusTCPTransaction trans = new ModbusTCPTransaction(conn);
trans.setRequest(req);
trans.execute();
ReadInputRegistersResponse res = (ReadInputRegistersResponse) trans.getResponse();
System.out.println(res.getRegisterValue(0));
conn.close();
「已知问题」这个词对 jamod 来说太轻了,它本身就是个问题。但如果你维护的是 2012 Jahr的老Das System,又不得不用它,那 openHAB 的 fork 比原版靠谱。
modbus-tk —— 快速原型的好帮手
GitHub: https://github.com/ljean/modbus-tk
法国人 Luc Jean 写的,名字里的 tk 是 TestKit 的缩写——定位非常明确:测试Werkzeuge。不是给生产环境用的。但实际上很多人拿它做了生产,因为它确实简单。
**Funktionscode**:01/02/03/04/05/06/15/16。不支持 22/23。
**传输模式**:RTU + TCP。ASCII 不支持。
**Hauptstation/Von der Station**:都支持。Von der Station可以很方便地 `add_slave` + `add_block` 创建模拟Ausrüstung。内置一个 hook 函数机制,可以在收zu读写Bitte时插入Custom definiert逻辑——这个设计很聪明,写测试Drehbuch的时候可以直接在 hook 里注入故障Szene。
**Beispiel Code**——RTU Hauptstation读Register.:
import serial
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
master = modbus_rtu.RtuMaster(
serial.Serial(port="/dev/ttyUSB0", baudrate=9600))
val = master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 1)
print(val[0])
**已知问题**: – 最后更新在 2020 Jahr左右,bug fix 基本靠社区 PR。Python 3.12 的兼容性可能有问题 – 没有Asynchron支持,所有Operationen都是同步阻塞的 – 浮点数没有内置辅助,你得自己 `struct.pack/unpack` – Hauptstation `execute()` 方法的超时行为不太可控,底层依赖 pyserial 的超时,遇zu无Antwort的Von der Station可能卡很久
**Dokumentation**:`examples/` 目录里几个Beispiel就是AllesDokumentation了。好在代码Quantität小,花十Unterteilung钟就能看完。
QtModbus —— Qt Entwickler的原生方案
这不是一个「库」,是 Qt 官方 `qtserialbus` 模块的一部Unterteilung。Qt 5.8 引入,现在是 Qt 6 的标配模块。
因为是 Qt 官方的,API 设计完全是 Qt 风格:信Nr.槽、Ereignisse循环、`QModbusReply`。跨平台天然支持——同一套代码在 Windows、Linux、macOS、Eingebettet Linux(Boot2Qt)上都能跑。
**Funktionscode**:通过 `QModbusDataUnit::RegisterType` 枚举支持所有标准Typus:Coils、DiscreteInputs、InputRegisters、HoldingRegisters。底层可以发Custom definiertFunktionscode。
**传输模式**:只有 TCP(`QModbusTcpClient` / `QModbusTcpServer`)。**没有 RTU**。这是一个重要的限制——Qt 官方没有内置 Modbus RTU 支持,你得用 `QSerialPort` 自己在应用层写 RTU 帧Analyse,或者找Die三方实现。有些Entwickler用 `QModbusRtuSerialMaster`(一个社区项目)来填补这个空缺。
**Hauptstation/Von der Station**:都支持。TCP Von der Station可以通过 `QModbusTcpServer` 实现,Custom definiertDaten映射zu `QModbusServer` 的Registrierung表。
**Beispiel Code**——TCP 客户端读一ein Register.:
#include <QModbusTcpClient>
#include <QModbusDataUnit>
auto client = new QModbusTcpClient(this);
client->setConnectionParameter(
QModbusDevice::NetworkAddressParameter, "192.168.1.100");
client->setConnectionParameter(
QModbusDevice::NetworkPortParameter, 502);
client->connectDevice();
QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 0, 1);
auto *reply = client->sendReadRequest(unit, 1);
connect(reply, &QModbusReply::finished, this, [reply]() {
qDebug() << reply->result().values().at(0);
});
Asynchron的,用信Nr.槽VerbindungErgebnis。注意 `sendReadRequest` 返回的 `QModbusReply*` 生命周期归 Qt 管理,别手动 delete。
**已知问题**: – 没有 RTU,这是最大的一个。你没看错,Qt 官方的 Modbus 模块没有 RTU – Verbindung断开后不会自动重连,你得在 `stateChanged` 信Nr.里自己写重连逻辑 – `QModbusTcpServer` 的 TCP Verbindung数有上限,默认是 1。要通过 `setMaxClients()` 改 – 许可问题:Qt 是 LGPL/GPL 双许可,商业闭源项目需要买 Qt Commercial License
**Dokumentation**:Qt 官方Dokumentation一流。Beispiel项目在 Qt Creator 欢迎页就能找zu。
新手推荐路径
别纠结了,按你的Techniken栈选:
– **STM32 裸机 / FreeRTOS** → FreeModbus。你没别的Auswahl,它就是标准答案。移植花半天,调通 3.5T 定时器再加半天,之后就不用管了 – **Linux Arbeitskontrolle机 / 网关(C)** → libmodbus。如果是Raspberry Pi跑 Debian 做 Modbus 网关,libmodbus + MQTT 桥接是经典方案。`libmodbus` 采集,`mosquitto` 上云 – **Python 上位机 / 测试Drehbuch** → pymodbus。pymodbus.simulator 仿真 + pymodbus client 读写,一个Drehbuch搞定AusrüstungTests。配合 pytest 可以做 Modbus 自动化测试 – **C# WinForm / WPF 上位机** → NModbus。NuGet 安装,三行代码开始读Register.。配合 ScottPlot 做实时曲线,工厂里最Häufig的Techniken栈组合 – **Qt 跨平台桌面应用** → QtModbus。如果你的应用已经用了 Qt,别引入额外的 C 库依赖,直接用 Qt 官方的 – **Java UnternehmenDas System(新项目)** → 不要用 jamod。用 j2mod(GitHub: steveohara/j2mod),它是 jamod 的现代化重写,API 清晰得多 – **快速验证想法** → modbus-tk。三Unterteilung钟搭一个Von der Station模拟器,验证Registerabbildung对不对,然后切zu pymodbus 做正式的
经典组合方案
**「FreeModbus Von der Station + pymodbus 上位机测试」**:EingebettetAusrüstung跑 FreeModbus 做Von der Station,开发阶段用 Python 写 pymodbus Drehbuch读写Register.做Funktion验证。比用 Modbus Poll 灵活——你能在Drehbuch里加DatenPrüfungen、边界测试、压力测试。调通之后,再换成真正的上位机(C# 或 Qt)。
**「libmodbus 网关 + pymodbus 配置Werkzeuge」**:Arbeitskontrolle机跑 libmodbus 对接下面几十台 Modbus RTU Ausrüstung,Daten收集后转 MQTT 上云。Web 后台用 pymodbus 做AusrüstungParameter读写——不要求实时性,Python 的开发效率碾压一切。
**「QtModbus 做界面 + libmodbus 做底层」**:Qt 写跨平台桌面 SCADA,人机交互和图表用 Qt Charts,但 Modbus Kommunikation不直接用 QtModbus(因为没有 RTU),而是通过 libmodbus 的 C API 做底层采集,Qt 只负责显示。这个组合在厂区监控Das System里很Häufig。
避坑清单
**Die一坑:FreeModbus 的 3.5T 定时器**
Modbus RTU Vereinbarung规定帧与帧之间至少间隔 3.5 个CharaktereZeit。Porter Rate 9600 时一个Charaktere大约 1ms,3.5T ≈ 3.5ms。很多人移植时直接把定时器设成 3.5ms 周期中断。错了。FreeModbus 的 3.5T 定时器用法是:每收zu一个Bytes就Ersetzen定时器,如果定时器溢出(说明 3.5T 内没有新Bytes),则认为一帧Ende。所以定时器要设成单次模式,不是周期模式。在收zuBytes的中断里调 `vMBPortTimersEnable()` 重新启动定时器。
Porter Rate不同时 3.5T 对应的Zeit不同:9600bps → ~3.65ms,19200bps → ~1.83ms,115200bps → ~304μs。115200 下 3.5T 只有 300 微秒左右,如果你的定时器最小粒度是 1ms,校准不了那么精细,帧间隔检测就会出错。这时候要么降Porter Ratezu 38400,要么用硬件定时器的hohe Präzision模式。
**Die二坑:libmodbus 的 connect vs new_tcp vs listen 语义**
`modbus_new_tcp(“192.168.1.100”, 502)` 创建上下文,但还没Verbindung。 `modbus_connect(ctx)` 在 RTU 模式下Öffnen Sie die Serie.,在 TCP Hauptstation模式下 connect zuDer Server。 TCP Von der Station模式不要调 `modbus_connect()`,而是 `modbus_tcp_listen(ctx, 1)` + `modbus_tcp_accept(ctx, &socket)`。
最Häufig的Fehler.:写 TCP Von der Station的时候习惯性调了 `modbus_connect()`,然后发现怎么都收不zuHauptstation的Bitte。因为 `connect()` 是去连别人,不是等别人来连你。
另外一个坑:`modbus_free(ctx)` 之后 `ctx` 指针还在。如果你要在循环里重连(比如网络断了又恢复),必须先 `ctx = NULL` 再 `modbus_new_tcp()`,否则有概率访问已释放的内存。Wireshark 抓包会看zu TCP SYN 疯狂重发几万次——那是 `modbus_connect()` 在访问野指针。
**Die三坑:pymodbus 同步 vs Asynchron模式混用**
pymodbus 3.x 有两套客户端 API:同步的 `ModbusSerialClient` / `ModbusTcpClient`,Asynchron的 `AsyncModbusSerialClient` / `AsyncModbusTcpClient`。
如果你在一个已经有 asyncio Ereignisse循环的进程里用同步客户端,底层的 socket I/O 会阻塞Ereignisse循环,导致所有Asynchron任务暂停。反过来,在纯同步Drehbuch里用Asynchron客户端,`await` 语法会报错。
Regeln很简单:要么全同步,要么全Asynchron。测试Drehbuch一般用同步就够了。生产环境如果是一个进程要同时连几十台Ausrüstung,必须用Asynchron模式,不然一Ein Gerät超时拖着其他 49 个一起等。
**Die四坑:Befehlseite问题——不是库的锅,但每次都是坑**
Das Modbus-Protokoll本身只定义了 16 位Register.的传输Das Format——大端(Big-Endian),hohe Bytes在前。但当你用两ein Register.传一个 32 位浮点数时,谁在前谁在后,Vereinbarung没说。不同厂商的处理方式不一样:
– 施耐德 PLC 用大端双字(ABCD):Register. N 存高 16 位,N+1 存低 16 位 – 西门子 S7-1200 用Bytes交换后的Das Format(CDAB 或 BADC) – 有些国产仪表用纯小端(DCBA)
libmodbus 提供了 `modbus_set_float()` 和四种Befehlseite常Quantität,pymodbus 有 `BinaryPayloadDecoder` 可以指定Befehlseite,FreeModbus 什么都没有——自己用 `union` 或者 `memcpy` 拼。
血的教训:调了两天发现Temperatur读数是个天文数字,最后是Befehlseite反了。先Bestätigen对方Ausrüstung的手册上有没有写 Float 的存放Das Format。如果没写,读两ein Register.自己拼,换四种排列总有一个是对的。
**Die五坑:RundfunkAdresse 0 的坑**
Modbus 规定Adresse 0 是RundfunkAdresse,Hauptstation发Rundfunk帧,所有Von der Station执行但不回复。但实际上很多Von der StationAusrüstung根本不支持Rundfunk,发Adresse 0 过去直接没反应。还有Die Ausrüstung虽然支持Rundfunk但不全支持——06(Schreiben eines einzelnen Registers)Rundfunk能执行,16(Schreiben mehrerer Register)Rundfunk就忽略。
如果你在用 `libmodbus_set_slave(ctx, 0)` 发Rundfunk,别指望有回复。`modbus_read_registers()` 在Rundfunk模式下的行为是未定义的。
选型决策速查
如果你不想看上面洋洋洒洒几千字,这里有个决策树:
1. 目标平台是 MCU 裸机 → FreeModbus 2. 目标平台是 Linux → libmodbus 3. 你用 Python → pymodbus 4. 你用 C# / .NET → NModbus 5. 你用 Qt → QtModbus(TCP Szene)或 libmodbus(RTU Szene) 6. 你用 Java 新项目 → j2mod,别碰 jamod 7. 你只是要快速搭个测试 → modbus-tk,验证完切 pymodbus
所有库我都贴了最小可BetriebBeispiel,Kopieren.粘贴改一下Geräte Adresse就能跑。Kommunikation调不通的时候,先拿 Modbus Poll 或 pymodbus 搭个纯软件环回Bestätigen硬件链路没问题,再怀疑Vereinbarung栈的 bug。
有问题zu modbus.cn 论坛聊。
Antwort veröffentlichen