你なぜか。要看这件の記事
这个問題在 Stack Overflow、control.com、CSDN 上被问了几千次——「我该用哪个开源 Modbus 库?」。每次回答都是零散的几句,没人系统对比过。中文社区更惨,搜出来的帖子一半在贴十年前 NModbus4 的代码,连 NModbus 主仓库已经迁移到 3.0.x 了都不知道。
我花了三天时间把这七个プロトコルスタック的仓库翻了一遍,跑了每个的最小サンプル,確認了维护ステータス。下面是结果。もし你赶时间,直接跳到「新手おすすめ路径」那一段,选你的プラットフォーム对应的库,开工。
总览对比表
| プロトコルスタック | 语言 | 许可 | Star 数 | 维护ステータス | master | slave | RTU | TCP | 适合谁 |
|---|---|---|---|---|---|---|---|---|---|
| FreeModbus | C | BSD | ~1.5k | 低活跃 | 有料 | ✅ | ✅ | ✅ | STM32 裸机/RTOS |
| libmodbus | C | LGPL v2.1+ | ~3.5k | 活跃 | ✅ | ✅ | ✅ | ✅ | Linux 工控机/ゲートウェイ |
| pymodbus | Python | BSD | ~2.2k | 非常活跃 | ✅ | ✅ | ✅ | ✅ | トップマシン/测试脚本 |
| NModbus | C# | MIT | ~700 | 活跃 | ✅ | ✅ | ✅ | ✅ | .NET/WinForm トップマシン |
| jamod | Java | Apache 2.0 | ~300 | 停滞 | ✅ | ✅ | ✅ | ✅ | Java 遗留系统 |
| modbus-tk | Python | LGPL | ~500 | 低活跃 | ✅ | ✅ | ✅ | ✅ | 快速原型 |
| QtModbus | C++ | LGPL/GPL | Qt 内置 | 活跃 | ✅ | ✅ | ❌ | ✅ | Qt 跨プラットフォーム应用 |
Star 数是我在 2026 year 6 月抓的,大致数量级对,具体数字你去 GitHub 看一眼就知道。
FreeModbus —— エンベデッド·イン裸机的標準答案
GitHub: https://github.com/cwalter-at/freemodbus
FreeModbus 是 Christian Walter 写的,一个奥地利エンベデッド·インエンジニア。这东西在 STM32 圈子里的地位相当于 Linux 内核里的 ext4——你ではない不能用别的,但用它是最不会出错的。
**代码体积**:编译完大约 6-12KB ROM,取决于你开了哪些関数コードと传输モード。RAM 开销几百バイト,主要是那几块データバッファ和事件队列。基本上是个 Cortex-M0 就能跑。
**機能コードのサポート**:03(read holding registers)、04(read input registers)、06(write single register)、16(write multiple registers)、01(リードコイルを読む)、02(read discrete inputs)、05(write single coil)、15(write multiple coils)。还有 17(駅からの報告 ID)。注意,ない 22(掩码写レジスタ)和 23(read and write multiple registers),需要的话得自己加。
**传输モード**:RTU、ASCII、TCP 都サポート,経由编译宏开关。
**master/slave**:这是 FreeModbus 最容易被误解的地方。官方仓库只开源了スレーブ代码,マスター是有料的。GitHub 上有不少社区魔改版加了マスター功能,比如 armink 的 FreeModbus_Slave-Master-RTT-STM32,开源的,质量不错,但ではない官方维护。用这些第三方版本的时候注意:タイムアウト処理和重试逻辑実装得很粗糙,别直接上生产。
**Code Example**——STM32 上初期化一个 RTU slave,address 1,Baud rate 9600,无Verification:
#include "mb.h"
int main(void) {
eMBInit(MB_RTU, 0x01, 0, 9600, MB_PAR_NONE);
eMBEnable();
while (1) {
eMBPoll();
}
}
就这三行。`eMBPoll()` 里跑着整个プロトコルスタック的ステータス机,非阻塞的,你需要在タイマータイマー。中断里喂 3.5T タイムアウト信号给它。这个 3.5T タイマータイマー。是 FreeModbus 移植的头号坑,下面会专门讲。
**已知問題**: - 官方仓库更新极慢,最后的大版本 v1.6 已经好几年没动了,bug 修不修看缘分 - 只サポート单シリアルポート,一个プロトコルスタック实例只能绑定一个 UART,多シリアルポート场景要改代码 - TCP モード用的是 lwIP raw API,ではない socket,这意味着 FreeRTOS+LWIP 环境下能用,但 Linux 上根本跑不了 TCP モード - ない浮動小数点数処理辅助函数,大小の変換自己写
**Document**:只有一份 API Document,HTML 格式的,够用但谈不上好。中文社区チュートリアル倒是多,CSDN 搜一下一堆。
libmodbus —— Linux 工控机的不二之选
GitHub: https://github.com/stephane/libmodbus
维护者 Stéphane Raimbault,法国人。libmodbus 是 C 语言写的最成熟的 Modbus 库,ない之一。3.5k star ではない白来的。
这个库的设计思路跟 FreeModbus 完全不同。FreeModbus 是为リソース受限的 MCU 设计的,用回调函数和ステータス机。libmodbus 是 POSIX 风格的,阻塞 API,`modbus_read_registers()` 调用会一直等到データ回来或タイムアウト。写工控机程序的人喜欢这种风格——简单直接,不用管什么ステータス机。
**機能コードのサポート**:几乎すべての。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 四种バイトオーダー。
**传输モード**:RTU + TCP 全サポート。同一套 API,`modbus_new_rtu()` 作成シリアルポートContextより,`modbus_new_tcp()` 作成 TCP Contextより,之后読み書き接口完全一样。
**master/slave**:都サポート。TCP スレーブ用 `modbus_tcp_listen()` + `modbus_tcp_accept()`,和写 Linux socket サーバー側。一个套路。
**Code Example**——駅から読む。 1 保持レジスタです。 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()` Open the serial port,TCP モード下调的是 `connect()` 连サーバー·サーバー。TCP 駅からのモデル必要なし。也不能调 `modbus_connect()`,而是用 `modbus_tcp_listen()`。搞混了连不上还不知道なぜか。 - `modbus_free()` 之后指针不会自动置空。もし你在循环里再接続,先 free 再 new,不手动 `ctx = NULL` 的话,偶尔会指向已释放的内存,表现为随机崩溃或疯狂再接続。这个我吃过亏 - 线程不セキュリティ。一个 `modbus_t*` Contextより不能被2つ线程同时操作,得自己加锁 - Windows 下シリアルポート名是 `\\.\COM10` 这种格式,Linux 是 `/dev/ttyUSB0`,跨プラットフォーム编译要注意
**Document**:官网 libmodbus.org 有一套 manual page 风格的ドキュメント,外加 mkdocs オンライン版。清晰但没什么サンプルプロジェクト,就 `tests/` 目录下那几个。
pymodbus —— Python 生态的事实標準
GitHub: https://github.com/pymodbus-dev/pymodbus
pymodbus 是目前维护最活跃的 Modbus 库,ない之一。pymodbus-dev 组织接手后,3.x 重写了非同期アーキテクチャ,サポート asyncio,还在持续发版。2024 年底最新的稳定版是 v3.6.x。
**function code**:全サポート。01/02/03/04/05/06/15/16/22/23,连 43(読み取りデバイスの識別)都有。
**传输モード**:RTU + TCP + TLS。TLS サポート是 pymodbus 3.x 新加的,可以直接跑 `modbus+tls://`。ASCII モード也サポート但在 3.x 里被标记为废弃。
**master/slave**:都サポート,而且サポート同步和异步两种 API。スレーブ可以跑一个完全的Simulator(シミュレータ)——`pymodbus.simulator` 能从 JSON 設定文件启动一个带多块レジスタ的虚拟デバイス,トップマシン开发デバッグ的时候非常好用。
**Code Example**——同步モード读一レジスタを保持する。:
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()
异步版稍微多几行,用 `async with` Contextより管理器,配合 asyncio 跑。
**已知問題**: - 2.x to 3.x 的 API 变化巨大。`pymodbus.client.sync.ModbusSerialClient` 变成了 `pymodbus.client.ModbusSerialClient`,`read_holding_registers` 戻り値は从 `ReadHoldingRegistersResponse` 变成了 `ModbusResponse`。もし你在网上搜到的サンプルコード用的是 `from pymodbus.client.sync import ...`,那肯定是 2.x 的,别直接抄 - 同步モード和异步モード不能混用。同一个进程里もし已经跑了 asyncio event loop,同步クライアント側は会阻塞事件循环导致タイムアウト - RTU モード下シリアルポートタイムアウト設定比较敏感。デフォルト的 3 秒タイムアウト对于低速デバイス(4800bps)可能不够,需要自己调到 5-10 秒 - pip インストール时 `pip install pymodbus`,ではない `pymodbus3` 或 `pymodbus2`,别装错了
**Document**:readthedocs 上有完全的ドキュメント,`examples/` 目录下有几十个サンプル脚本。ない中文ドキュメント,但英文很清晰。
NModbus —— .NET プラットフォーム的唯一严肃選択
GitHub: https://github.com/NModbus/NModbus
NModbus 的历史有点绕。最早的 NModbus 是 Google Code 上(对,就是那个 Google Code)的一个项目,后来迁移到 GitHub 变成 NModbus4,再后来 NModbus4 也停更了。现在的 NModbus/NModbus 是 NModbus4 的继任者,维护者 rquackenbush,活跃开发中,nuget 包名 `NModbus`,最新版 3.0.x,サポート .NET 6+。
**function code**:01/02/03/04/05/06/15/16 全サポート。22 和 23 需要自定义機能コード処理。
**传输モード**:RTU、ASCII、TCP、UDP 全サポート。シリアルポート経由 `NModbus.Serial` 包,サポート Windows/Linux。
**master/slave**:都サポート。スレーブサポート自定义データストア,可以把レジスタマップ到内存、データベースの種類甚至 PLC。
**Code Example**——TCP マスター读一1つのレジスタ:
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]);
**已知問題**: - シリアルポートサポート依赖 `System.IO.Ports`,Linux 上需要额外設定权限 - `SlaveDataStore` 在多线程下ではない线程セキュリティ的,高い同時性読み書き时要自己加锁 - asynchronous API(`ReadHoldingRegistersAsync`)戻る `Task`,但底层 I/O 实际上是同步的,ない真正的 async I/O
**Document**:README 够用,`Samples/` 目录有几个サンプル。主要靠 Stack Overflow 上的老帖子。
jamod —— Java 生态的「前辈」,但建议你别用
SourceForge: https://sourceforge.net/projects/jamod/ GitHub (openHAB fork): https://github.com/openhab/jamod
jamod 是 Dieter Wimberger 在 2002 年写的,比在座很多エンジニア的工龄都长。最后一次实质性更新是 2010 year,之后基本就ない了。openHAB 社区 fork 了一个版本修了几个 bug 给自己用,但那个 fork 也只是被动维护。
もし你现在新开一个 Java 项目要做 Modbus,直接跳过 jamod,看 j2mod(GitHub: steveohara/j2mod)。j2mod 是 jamod 的重写版本,Apache 2.0 许可,Java 8+,还在更新(2024 year 7 月最后一次送信),RTU + TCP 全サポート,マスタースレーブ都有。
但既然这件の記事要カバー jamod,我まだ写上。jamod サポート的機能コード:01/02/03/04/05/06/15/16。传输モード RTU + ASCII + TCP。シリアル通信依赖 `javax.comm`(巨古老的 API,JDK 都不自带了),替代方案是 RXTX 或 jSerialComm。
Code Example:
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 年的老系统,又不得不用它,那 openHAB 的 fork 比原版靠谱。
modbus-tk —— 快速原型的好帮手
GitHub: https://github.com/ljean/modbus-tk
法国人 Luc Jean 写的,名字里的 tk 是 TestKit 的缩写——ポジショニング非常明确:测试工具。ではない给生产环境用的。但实际上很多人拿它做了生产,因为它确实简单。
**function code**:01/02/03/04/05/06/15/16。サポートなし。 22/23。
**传输モード**:RTU + TCP。ASCII サポートなし。。
**master/slave**:都サポート。スレーブ可以很方便地 `add_slave` + `add_block` 作成模拟デバイス。内置一个 hook 函数机制,可以在收到読み書きリクエスト时插入自定义逻辑——这个设计很聪明,写测试脚本的时候可以直接在 hook 里注入故障场景。
**Code Example**——RTU マスター读レジスタ:
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 年左右,bug fix 基本靠社区 PR。Python 3.12 的兼容性可能有問題 - ない异步サポート,すべての操作都是同步阻塞的 - 浮動小数点数ない内置辅助,你得自己 `struct.pack/unpack` - master `execute()` 方法的タイムアウト行为不太可控,底层依赖 pyserial 的タイムアウト,遇到応答なし。的スレーブ可能卡很久
**Document**:`examples/` 目录里几个サンプル就是すべてドキュメント了。好在代码量小,花十分就能看完。
QtModbus —— Qt 開発者たちは的原生方案
这ではない一个「库」,是 Qt 官方 `qtserialbus` モジュール的一部分。Qt 5.8 引入,现在是 Qt 6 的标配モジュール。
因为是 Qt 官方的,API 设计完全是 Qt 风格:信号槽、事件循环、`QModbusReply`。跨プラットフォーム天然サポート——同一套代码在 Windows、Linux、macOS、embedded Linux(Boot2Qt)上都能跑。
**function code**:経由 `QModbusDataUnit::RegisterType` 枚举サポートすべての標準タイプ:Coils、DiscreteInputs、InputRegisters、HoldingRegisters。底层可以发自定义機能コード。
**传输モード**:只有 TCP(`QModbusTcpClient` / `QModbusTcpServer`)。**ない RTU**。这是一个重要的限制——Qt 官方ない内置 Modbus RTU サポート,你得用 `QSerialPort` 自己在アプリケーション層写 RTU フレーム解析,或者找第三方実装。一部の開発者たちは用 `QModbusRtuSerialMaster`(一个社区项目)来填补这个空缺。
**master/slave**:都サポート。TCP スレーブ可以経由 `QModbusTcpServer` 実装,自定义データ·マッピング到 `QModbusServer` 的登録表。
**Code Example**——TCP クライアント側は读一1つのレジスタ:
#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);
});
异步的,用信号槽连接结果。注意 `sendReadRequest` 戻る的 `QModbusReply*` 生命周期归 Qt 管理,别手动 delete。
**已知問題**: - ない RTU,这是最大的一个。你没看错,Qt 官方的 Modbus モジュールない RTU - 连接断开后不会自動再接続。,你得在 `stateChanged` 信号里自己写再接続逻辑 - `QModbusTcpServer` 的 TCP 连接数有上限,デフォルト是 1。要経由 `setMaxClients()` 改 - 许可問題:Qt 是 LGPL/GPL 双许可,商业闭源项目需要买 Qt Commercial License
**Document**:Qt 官方ドキュメント一流。サンプルプロジェクト在 Qt Creator 欢迎页就能找到。
新手おすすめ路径
别纠结了,按你的技术栈选:
- **STM32 裸机 / FreeRTOS** → FreeModbus。你没别的選択,它就是標準答案。移植花半天,调通 3.5T タイマータイマー。再加半天,之后就不用管了 - **Linux 工控机 / ゲートウェイ(C)** → libmodbus。もしそうならRaspberry Piについて跑 Debian 做 Modbus ゲートウェイ,libmodbus + MQTT 桥接是经典方案。`libmodbus` 采集,`mosquitto` 上云 - **Python トップマシン / 测试脚本** → pymodbus。pymodbus.simulator 仿真 + pymodbus client 読み書き,一个脚本搞定デバイスデバッグ。配合 pytest 可以做 Modbus 自動化测试 - **C# WinForm / WPF トップマシン** → NModbus。NuGet インストール,三行代码読み始めましたレジスタ。配合 ScottPlot 做实时曲线,工厂里最も一般的な的技术栈组合 - **Qt 跨プラットフォーム桌面应用** → QtModbus。もし你的应用已经用了 Qt,别引入额外的 C 库依赖,直接使用する。 Qt 官方的 - **Java 企业系统(新项目)** → 不要用 jamod。用 j2mod(GitHub: steveohara/j2mod),它是 jamod 的现代化重写,API 清晰得多 - **快速验证想法** → modbus-tk。三分搭一个ステーションからのシミュレーション器,验证レジスタマップそうですね。,然后切到 pymodbus 做正式的
经典组合方案
**「FreeModbus slave + pymodbus トップマシン测试」**:組込みデバイス跑 FreeModbus 做スレーブ,开发阶段用 Python 写 pymodbus 脚本読み取り/書き込みレジスタ做功能验证。比用 Modbus Poll 灵活——你能在脚本里加データチェック、边界测试、压力测试。调通之后,再换成真正的トップマシン(C# 或 Qt)。
**「libmodbus ゲートウェイ + pymodbus 設定工具」**:工控机跑 libmodbus 对接下面几十台 Modbus RTU device,データ收集后转 MQTT 上云。Web 后台用 pymodbus 做デバイス参数読み書き——不要求实时性,Python 的开发效率碾压一切。
**「QtModbus 做界面 + libmodbus 做底层」**:Qt 写跨プラットフォーム桌面 SCADA,人机交互和图表用 Qt Charts,但 Modbus 通信不直接使用する。 QtModbus(因为ない RTU),而是経由 libmodbus 的 C API 做底层采集,Qt 只负责表示。这个组合在厂区モニタリング系统里很常见。
避坑清单
**第一坑:FreeModbus 的 3.5T タイマータイマー。**
Modbus RTU 協定の規定フレーム与フレーム之间至少間隔 3.5 个文字の時間。Baud rate 9600 时一个文字大约 1ms,3.5T ≈ 3.5ms。很多人移植时直接把タイマータイマー。设成 3.5ms 周期中断。错了。FreeModbus 的 3.5T タイマータイマー。用法是:每收到一バイト単位。就リセットタイマータイマー。,もしタイマータイマー。溢出(説明 3.5T に新しいものはないバイト),则认为一フレーム结束。所以タイマータイマー。要设成单次モード,ではない周期モード。在收到バイト的中断里调 `vMBPortTimersEnable()` 重新启动タイマータイマー。。
ボーレート不同时 3.5T 对应的时间不同:9600bps → ~3.65ms,19200bps → ~1.83ms,115200bps → ~304μs。115200 下 3.5T 只有 300 微秒左右,もし你的タイマータイマー。最小粒度是 1ms,校准不了那么精细,フレーム間隔検出就会出错。这时候要么ボーレートを下げる。 38400,要么用硬件タイマータイマー。的高精度モード。
**第二坑:libmodbus 的 connect vs new_tcp vs listen 语义**
`modbus_new_tcp("192.168.1.100", 502)` 作成Contextより,但还没连接。 `modbus_connect(ctx)` 在 RTU モード下シリアルポートを開く,在 TCP マスターモード下 connect 到サーバー·サーバー。 TCP 駅からのモデル不要调 `modbus_connect()`,而是 `modbus_tcp_listen(ctx, 1)` + `modbus_tcp_accept(ctx, &socket)`。
最も一般的な的エラー:写 TCP スレーブ的时候习惯性调了 `modbus_connect()`,然后发现怎么都受信できない。マスター的リクエスト。因为 `connect()` 是去连别人,ではない等别人来连你。
另外一个坑:`modbus_free(ctx)` 之后 `ctx` 指针还在。もし你要在循环里再接続(比如网络断了又恢复),まず必要です。 `ctx = NULL` 再 `modbus_new_tcp()`,否则有概率アクセス已释放的内存。Wireshark 抓包会看到 TCP SYN 疯狂重发几万次——那是 `modbus_connect()` 在アクセス野指针。
**第三坑:pymodbus 同步 vs 异步モード混用**
pymodbus 3.x 有两套クライアント側は API:同步的 `ModbusSerialClient` / `ModbusTcpClient`,异步的 `AsyncModbusSerialClient` / `AsyncModbusTcpClient`。
もし你在一个已经有 asyncio 事件循环的进程里用同步クライアント側は,底层的 socket I/O 会阻塞事件循环,导致すべての异步任务暂停。反过来,在纯同步脚本里用异步クライアント側は,`await` 语法会报错。
ルール很简单:要么全同步,要么完全に非同期。测试脚本一般用同步就够了。生产环境もしそうなら一个进程要同时连几十台デバイス,必须用异步モード,不然一个デバイスタイムアウト拖着其他 49 个一起等。
**第四坑:バイトオーダー問題——ではない库的锅,但每次都是坑**
Modbus protocol本身只定义了 16 位レジスタ的传输格式——ビッグエンディアン(Big-Endian),前の高さ。。但当你用两1つのレジスタ传一个 32 ビット浮動小数点数时,谁前に谁在后,协议没说。不同厂商的処理方式不一样:
- シュナイダー PLC 用ビッグエンディアン双字(ABCD):register N 存高 16 位,N+1 存低 16 位 - シーメンス S7-1200 用バイトスワップ后的格式(CDAB 或 BADC) - 一部の国产仪表用纯リトルエンディアン(DCBA)
libmodbus 提供了 `modbus_set_float()` 和四种バイトオーダー常量,pymodbus 有 `BinaryPayloadDecoder` 可以指定バイトオーダー,FreeModbus 什么都ない——自己用 `union` 或者 `memcpy` 拼。
血的教训:调了两天发现温度读数是个天文数字,最后是バイトオーダー反了。先確認对方デバイス的手册上有ない写 Float 的存放格式。もし没写,读两1つのレジスタ自己拼,换四種の配列。总有一个是对的。
**第五坑:放送アドレス 0 的坑**
Modbus 规定アドレス 0 是放送アドレス,マスター发广播フレーム,すべての駅から。执行但不回复。但实际上很多スレーブデバイス根本不放送のサポート,发アドレス 0 过去直接没反应。还有的デバイス虽然放送のサポート但不全サポート——06(write single register)广播能执行,16(write multiple registers)广播就忽略。
もし你在用 `libmodbus_set_slave(ctx, 0)` 发广播,别指望有回复。`modbus_read_registers()` 在广播モード下的行为是未定义的。
选型决策速查
もし你不想看上面洋洋洒洒几千字,这里有个决策树:
1. 目标プラットフォーム是 MCU 裸机 → FreeModbus 2. 目标プラットフォーム是 Linux → libmodbus 3. 你用 Python → pymodbus 4. 你用 C# / .NET → NModbus 5. 你用 Qt → QtModbus(TCP Scenarios)或 libmodbus(RTU Scenarios) 6. 你用 Java 新项目 → j2mod,别碰 jamod 7. 你只是要快速搭个测试 → modbus-tk,验证完切 pymodbus
すべての库我都贴了最小可运行サンプル,コピー貼り付け改一下デバイスアドレス就能跑。通信调通信不可的时候,先拿 Modbus Poll 或 pymodbus 搭个纯软件环回確認硬件链路没問題,再怀疑プロトコルスタック的 bug。
有問題到 modbus.cn 论坛聊。
Leave a Reply