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的功能码和数据模型,那才是真正干活要用到的东西。