modbus-esp8266 API终极速查表:readHreg、writeCoil、push/pull一览无余
【免费下载链接】modbus-esp8266Most complete Modbus library for Arduino. A library that allows your Arduino board to communicate via Modbus protocol, acting as a master, slave or both. Supports network transport (Modbus TCP) and Serial line/RS-485 (Modbus RTU). Supports Modbus TCP Security for ESP8266/ESP32.项目地址: https://gitcode.com/gh_mirrors/mo/modbus-esp8266
modbus-esp8266是 Arduino 平台最完整的 Modbus 协议库,让 ESP8266 / ESP32 单板即可充当 Modbus 主站或从站,同时支持 Modbus RTU(RS-485 串口)与 Modbus TCP(WiFi/以太网)两种传输,并内置 Modbus TCP Security 安全扩展。本文以速查表形式整理其核心 API:从readHreg、writeCoil读写接口,到push/pull数据中转、task() 异步机制与回调函数,一篇看全。
📌 完整接口签名见 documentation/API.md,核心类与功能码定义见 src/Modbus.h。
30秒入门:4 种寄存器类型
Modbus 只有 4 类寄存器,所有 API 都是围绕它们设计的:
| 名称 | 宏 | 功能码 | 类型 | 特点 |
|---|---|---|---|---|
| Coil | COIL(n) | 0x01 读 / 0x05 写 | bool | 可读可写,控制输出 |
| Ists | ISTS(n) | 0x02 | bool | 只读,离散输入 |
| Hreg | HREG(n) | 0x03 | uint16_t | 可读可写,保持寄存器 |
| Ireg | IREG(n) | 0x04 | uint16_t | 只读,输入寄存器 |
💡 注意:Modbus 标准只有"位"和"16 位"两种数据类型。
float、uint32_t等有符号/浮点值需要拆分成多个 16 位寄存器传输。
服务端速查:addHreg 与本地寄存器读写
作为从站(server/slave),先注册本地寄存器,再用同名函数读写:
| 操作 | API | 说明 |
|---|---|---|
| 注册 | addHreg(offset, value, numregs) | 建立从站地址空间,Coil/Ists/Ireg 同理 |
| 写本地 | Hreg(offset, value) | Coil(offset, bool)、Ists、Ireg同理 |
| 读本地 | Hreg(offset) | 单参重载即读,返回uint16_t |
| 删除 | removeHreg(offset, numregs) | 从地址空间移除寄存器 |
这些接口的完整签名可参考 src/Modbus.h。
客户端读写:readHreg 与 writeCoil 怎么用
作为主站(master/client),调用格式高度统一:读写函数(从站ID, 起始地址, 值/数组指针, 寄存器数, 事务回调):
| 操作 | API | 对应功能码 |
|---|---|---|
| 读线圈 | readCoil(slaveId, offset, value, numregs, cb) | 0x01 |
| 读离散输入 | readIsts(slaveId, offset, value, numregs, cb) | 0x02 |
| 读保持寄存器 | readHreg(slaveId, offset, value, numregs, cb) | 0x03 |
| 读输入寄存器 | readIreg(slaveId, offset, value, numregs, cb) | 0x04 |
| 写单个线圈 | writeCoil(slaveId, offset, value, cb) | 0x05 |
| 写单个寄存器 | writeHreg(slaveId, offset, value, cb) | 0x06 |
| 批量写 | writeCoil(slaveId, offset, value, numregs, cb) | 0x0F / 0x10 |
批量写重载会根据numregs自动选择单写或多写功能码,无需手动区分。Modbus TCP 模式下,把slaveId换成IPAddress(可加uint单元标识参数)即可直连对端。
push/pull 数据中转:一行代码完成"远程↔本地"复制
push/pull 是最容易混淆的一组接口,记住一个方向口诀即可:
- pull= 把远程数据拉下来,存进本地寄存器:
pullHreg(slaveId, from, to, numregs),from是远程起始地址,to是本地保存地址 - push= 把本地数据推上去,写到远程:
pushHreg(slaveId, to, from, numregs),to是远程地址,from是本地数据地址 - 跨类型中转同样支持:
pullCoilToIsts、pushIregToHreg、pullIsts、pushIstsToCoil等
🔧 典型场景:做 TCP 到 RTU 的协议桥接、把传感器数据自动缓存到本地寄存器,都靠它一行解决,官方桥接示例见 examples/Bridge/。
别忘了 task():异步调用工作流
这是新手最常踩的坑:所有 read/write/pull/push 都是异步的。readHreg()只是发出请求就立刻返回,真正的应答处理由task()完成。所以loop()里必须周期性调用:
void loop() { if (!mb.slave()) { // 无进行中的请求时才发新请求 mb.readCoil(1, 1, coils, 20, cbWrite); } mb.task(); // 处理应答、触发事务回调 yield(); }上面的完整主站示例可参考 examples/RTU/master/master.ino,从站示例见 examples/RTU/slave/slave.ino。
图:服务端 task() 收到请求后的处理流程(onRequest 回调 → 参数校验 → 准备应答 → 触发 onGet/onSet 回调)
⚠️ 两个高频现象都是异步机制的正常表现:
- 调用 readHreg 后立刻读值读不到—— 应答可能还没回来,由
task()异步填充; - 连续调用多次 read/write 只有第一次执行—— 同一时间只允许一个请求在途,
task()处理完前请等待。
回调速查:onSetHreg、onGetCoil 与事务通知
| 回调 | 触发时机 |
|---|---|
onSetCoil / onSetHreg / onSetIsts / onSetIreg(addr, cb, numregs) | 本地寄存器被写时 |
onGetCoil / onGetHreg / onGetIsts / onGetIreg(addr, cb, numregs) | 本地寄存器被读时 |
事务回调cbTransaction | 每个 read/write/push/pull 请求结束时(成功或超时) |
onConnect / onDisconnect | TCP 服务器连接建立/断开事件 |
在回调内调用eventSource()可获取请求来源:RTU 下返回从站 ID,TCP 下返回对方 IP(超时事务返回INADDR_NONE)。回调用法示例见 examples/Callback/onGetShared/onGetShared.ino 与 examples/Callback/onSet/onSet.ino。
错误码速查表
所有客户端调用返回事务 ID,结果通过事务回调以ResultCode形式通知,常见值:
| 错误码 | 含义 | 排查建议 |
|---|---|---|
0x00 | 成功 | — |
0x01 | 功能码不支持 | 检查从站是否实现该功能 |
0x02 | 地址非法 | 确认已addXxx注册该寄存器 |
0x03 | 值超范围 | 检查写入值 |
0xE4 | 超时 | RTU:查接线/波特率(可降到 9600)/换独立供电;TCP:ping 与防火墙排查 |
0xE5 | 连接丢失 | 检查对端在线状态 |
0xE6 | 事务被取消 | — |
传输层设置:RTU 与 TCP 快速上手
| 需求 | RTU(串口/RS-485) | TCP(网络) |
|---|---|---|
| 初始化 | begin(&Serial1, txEnablePin) | — |
| 设波特率 | setBaudrate(9600)(非 ESP 平台必调) | — |
| 从站模式 | server(slaveId) | server(port),默认 502 |
| 主站模式 | client()(或master()) | client(),配合connect(ip, port) |
| 自动重连 | — | autoConnect(true),默认关闭 |
RTU 的begin支持SoftwareSerial/HardwareSerial/任意Stream,txEnablePin用于 MAX-485 收发控制(低电平有效需传txEnableDirect=false)。RTU 接口签名见 src/ModbusRTU.h,编译期配置项(最大寄存器数、事务数等)在 src/ModbusSettings.h 中调整。
常见问题速答
- float / 32 位值怎么发?拆成多个 16 位寄存器,连续 read/write 后在应用层拼合。
- 0xE4 超时偶发?偶发可接受;频发则按上表 RTU/TCP 分别排查硬件与网络。
- 能做 TCP→RTU 桥吗?可以,参考 examples/Bridge/TCP-to-RTU-Simulator/ 及文档 documentation/README.md 中的 FAQ。
把这张速查表收藏起来,配合examples/目录里的分场景示例(RTU、TCP、TLS、桥接、OTA 文件更新),就能覆盖绝大多数 Modbus 开发需求 ✅
【免费下载链接】modbus-esp8266Most complete Modbus library for Arduino. A library that allows your Arduino board to communicate via Modbus protocol, acting as a master, slave or both. Supports network transport (Modbus TCP) and Serial line/RS-485 (Modbus RTU). Supports Modbus TCP Security for ESP8266/ESP32.项目地址: https://gitcode.com/gh_mirrors/mo/modbus-esp8266
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考