开篇
上一篇我们明白了:Modbus RTU 是 485 工业现场最通用的 “设备普通话”。很多新手写采集代码,只会网上复制现成函数,报文一乱、设备不回复就无从下手,根源就是看不懂原始十六进制报文。
本篇不用复杂寄存器原理,拿着真实收发报文逐字节拆解:地址、功能码、寄存器、CRC 校验一次性讲透,看完随便抓一条现场串口日志,就能反向算出指令、定位故障。
一、Modbus RTU 一帧完整报文固定 5 部分
一条下发查询指令标准结构:从站地址 + 功能码 + 起始寄存器地址 + 寄存器数量 + CRC16 校验设备回复报文:从站地址 + 功能码 + 数据长度 + 寄存器数据 + CRC16 校验
全是 16 进制数据,485 串口抓包看到的一串 HEX 字符,就是一帧完整对话。
字段简要说明
-
从站地址 (1 字节) :485 总线上多台设备区分编号,范围 1~247,单设备常用 01
-
功能码 (1 字节) :告诉设备读 / 写什么,现场最常用:
- 03:读保持寄存器(90% 仪表、PLC 读参数都用它)
- 06:单个寄存器写入
- 10:批量寄存器写入
-
寄存器地址 (2 字节) :要读取的点位起始位置
-
寄存器数量 (2 字节) :一次性连续读几个寄存器
-
CRC16 (2 字节) :整帧校验,错一字节设备直接丢弃不回复
二、实战举例:真实下发 + 应答报文拆解
需求:485 总线上 #01 电表,从 0000 地址读取 2 个寄存器(电压、电流)
主机下发查询指令:01 03 00 00 00 02 84 0A
逐段拆分:
01:从站地址 1 号设备03:功能码,读保持寄存器00 00:起始寄存器 0 地址00 02:连续读取 2 个寄存器84 0A:整条前面 6 个字节 CRC 校验值
下发含义:去 1 号设备,从 0 寄存器开始,连续读取 2 个寄存器数据。
设备返回应答报文:01 03 04 0BB8 0065 3C36
分段拆解:
01:回复 1 号从站03:对应读寄存器功能码04:后面有效数据总字节数,2 个寄存器 = 4 字节0B B8:第 1 个寄存器原始数据00 65:第 2 个寄存器原始数据3C 36:整包 CRC 校验
换算举例:仪表倍率 0.1,0BB8转十进制 = 3000 → 电压 300.0V;0065=101 → 电流 10.1A。日常现场读数据,就是这套换算逻辑。
三、新手高频 2 种异常报文(现场最常见故障)
1. 异常应答(设备报错)
例:01 83 02 XX XX
83=03 功能码异常标识(原值 + 0x80)- 02:异常码,代表寄存器地址不存在故障原因:下发寄存器地址超出设备手册范围,改地址即可。
2. 只收到乱码 / 无回复
- 从站地址写错,总线没有对应设备
- CRC 校验计算错误,设备直接丢包
- 485 A/B 线接反、硬件没加隔离,电气干扰乱码
日常现场 80% 读不到数据,都是上面三类问题。
四、写采集程序必记开发要点(量产避坑)
- CRC 不能随便用网上半成品函数不同字节高低位排布极易出错,RTU CRC 低字节在前、高字节在后,写错校验设备永远不回包。
- 寄存器是 2 字节一个点位一个寄存器存 16 位数据,浮点、多字节参数往往占用连续 2~4 个寄存器,要对照仪表说明书拆分。
- 轮询间隔不能过快485 总线单总线多设备,指令下发间隔小于 10ms 极易总线冲突、丢应答,常规现场推荐 50~100ms 轮询间隔。
- 收到应答先校验 CRCCRC 不通过直接丢弃数据包,不要解析脏数据,是防止乱码串数最廉价有效的手段。
五、日常调试快速落地小技巧
- 先用串口调试助手,手动拼 16 进制指令收发,调通硬件和协议,再移植代码
- 抓串口原始日志,对照报文,错在哪一字节一眼定位
- 先单设备调试,再挂多路 485 批量轮询
下篇预告
下一篇进入代码落地:C 语言最简 Modbus RTU 采集示例,实现指令组包、CRC 计算、数据解析,可直接移植到网关固件。
结尾
Modbus RTU 是网关开发基本功,看懂报文 = 现场排错少一半麻烦。市面上代码随处可得,但能对着报文快速定位硬件、协议故障,是老工程师不可替代的优势,也是接私活、做方案的核心竞争力。
本文为《网关开发从入门到落地》第 04 篇,需要协议调试、网关定制、项目方案可私信交流。