3、Modbus协议入门:从诞生到实战
各位同学,今天我们来聊聊Modbus。说实话,这可能是工业通信领域里最“老”但又最“活”的协议了。我入行那会儿,第一个接触的协议就是它。为什么?因为简单、可靠、遍地都是。
3.1 Modbus协议发展史:一个“意外”的行业标准
Modbus是1979年由Modicon公司(现在的施耐德电气)发明的。初衷很简单——让自家的PLC能跟其他设备通信。你想想看,那个年代可没有TCP/IP,更没有物联网的概念。
我记得有个老工程师跟我说过:“Modbus能活到今天,连发明它的人都没想到。”确实,它从Modicon的私有协议,慢慢变成了工业自动化领域的“通用语言”。
为什么能火?我个人觉得有几点:
- 开放免费:Modicon直接公开了协议规范,谁都能用
- 简单粗暴:报文结构清晰,实现起来不费劲
- 硬件门槛低:串口就能跑,成本几乎为零
2004年,Modbus被纳入IEC 61158标准,正式“转正”了。嗯,这就像野路子出身的功夫高手,终于拿到了官方段位证书。
3.2 Modbus RTU与ASCII模式:串口上的两种“方言”
Modbus在串口通信上有两种模式:RTU和ASCII。说白了,就是数据怎么打包、怎么传输的问题。
3.2.1 Modbus RTU模式
RTU模式是二进制传输,效率高。报文格式是这样的:
地址码(1字节) + 功能码(1字节) + 数据区(N字节) + CRC校验(2字节)
举个例子,读取从站地址为1的设备,保持寄存器起始地址0,读取2个寄存器:
请求:01 03 00 00 00 02 C4 0B
响应:01 03 04 00 0A 00 14 3A 86
这里要注意CRC校验。我曾经在项目里遇到过,CRC算错了,设备死活不响应。排查了半天,最后发现是校验算法里高低字节顺序搞反了。嗯,这种坑踩过一次就记住了。
RTU模式特点:
- 数据密度高,同样波特率下传输更快
- 报文帧有严格的时间间隔要求(3.5字符时间)
- CRC校验,可靠性高
3.2.2 Modbus ASCII模式
ASCII模式就是把每个字节拆成两个ASCII字符发送。比如0x1A,就发送字符'1'和'A'(十六进制表示)。
报文格式:
起始符':' + 地址码(2字符) + 功能码(2字符) + 数据区 + LRC校验(2字符) + 结束符'\r\n'
同样的读取操作,ASCII模式报文长这样:
请求::010300000002F8\r\n
响应::010304000A0014EA\r\n
你可能会问:“为什么还要用ASCII模式?效率这么低。”我告诉你,有些老设备或者无线通信场景,ASCII模式反而更稳定。因为字符传输对时序要求没那么严格,不容易丢帧。
我的建议:能上RTU就上RTU。除非设备只支持ASCII,或者通信链路质量特别差,否则别用ASCII。效率差太多了。
3.3 Modbus TCP/IP模式:串口协议的“网络化”改造
到了以太网时代,Modbus也得跟上。Modbus TCP/IP就是把RTU报文直接封装到TCP包里。说白了,就是把串口那套搬到网络上。
报文结构对比:
| 字段 | RTU | TCP/IP |
|---|---|---|
| 地址码 | 1字节 | 无(由IP地址标识) |
| 功能码 | 1字节 | 1字节 |
| 数据区 | N字节 | N字节 |
| 校验 | CRC(2字节) | 无(由TCP保证) |
| 额外头部 | 无 | MBAP头(7字节) |
MBAP头包含事务标识符、协议标识符、长度和单元标识符。其中单元标识符就是用来代替RTU里的地址码的。
我做过一个项目,现场有几十台设备通过Modbus TCP接入。一开始没注意,所有设备都用默认的502端口。结果发现,有些设备端口冲突了。后来统一规划了端口映射,才解决问题。这种细节,调试手册上可不会写。
注意:Modbus TCP没有CRC校验,因为TCP/IP协议栈自己会做校验。但这也意味着,如果TCP层出了问题,Modbus是不知道的。所以应用层最好加个超时重试机制。
3.4 物理层与数据链路层:从“线”到“帧”
Modbus的物理层和数据链路层,其实借用了很多现成的标准。
3.4.1 物理层
串口Modbus最常用的物理层是RS-485。为什么?因为:
- 差分信号,抗干扰能力强
- 支持多点通信(最多32个节点,加中继可以更多)
- 传输距离远(1200米没问题)
RS-232也有,但距离短(15米),只能点对点。我一般只在调试时用RS-232,正式项目都上RS-485。
Modbus TCP的物理层就是标准以太网,RJ45接口,100Mbps起步。没什么特别的。
3.4.2 数据链路层
Modbus的数据链路层,说白了就是怎么把数据组织成“帧”。
RTU模式的数据链路层特点:
- 帧间隔:至少3.5个字符时间
- 字节间隔:不超过1.5个字符时间
- 如果超过1.5个字符时间,接收方认为帧结束了
我曾经调试一个设备,发现它老是丢包。用示波器一看,原来是设备发送字节之间的间隔超过了1.5个字符时间。后来调整了设备的波特率,问题解决了。这种问题,光看代码是看不出来的。
ASCII模式的数据链路层就宽松多了:
- 帧起始:':' (0x3A)
- 帧结束:'\r\n' (0x0D 0x0A)
- 字符间隔没有严格要求
这也是为什么ASCII模式在无线通信中更受欢迎——对时序要求低,不容易出错。
总结一下:
- Modbus RTU:效率高,适合有线、稳定环境
- Modbus ASCII:容错好,适合无线、不稳定环境
- Modbus TCP:速度快,适合以太网环境
选哪种?看你的现场条件。没有绝对的好坏,只有合不合适。
好了,这一章就到这里。下一章我们讲Modbus的功能码和数据模型,那才是真正干活要用到的东西。