3、Modbus协议入门:Modbus协议发展史、Modbus RTU vs ASCII vs TCP、物理层与协议栈
3.1 从一根双绞线说起:Modbus的前世今生
说实话,我入行那会儿,Modbus就已经是工业通讯的「老大哥」了。1979年,Modicon公司为了给自家的PLC找个通用的通讯方式,搞出了这个协议。你想想看,那是个什么年代?没有以太网,没有Wi-Fi,连个人电脑都还是稀罕物。
但就是这么一个「老古董」,到现在还在工控圈子里活得好好的。为什么?因为它简单、可靠、开放。我见过不少项目,上位机换了好几代,底层的IO模块还是用Modbus RTU在跑。说白了,只要两根线不断,数据就能传,这就是Modbus的生命力。
Modbus协议的发展有几个关键节点:
- 1979年:Modicon发布Modbus串行协议,基于RS-232/RS-485物理层
- 1999年:施耐德电气将Modbus协议公开,成为真正的开放协议
- 2002年:Modbus TCP/IP标准发布,开始拥抱以太网
- 2007年:成为国家标准GB/T 19582
我个人习惯把Modbus的发展分成两个阶段:串口时代和以太网时代。串口时代解决的是「能不能通」的问题,以太网时代解决的是「通得快不快」的问题。但核心思想一直没变——主从问答,一主多从。
核心要点:Modbus本质上是一个应用层协议,它不关心底层是串口还是以太网。你只要把数据按照它的格式打包好,用什么物理层传都行。这也是它能活40多年的根本原因。
3.2 Modbus RTU vs ASCII vs TCP:三种变体的选择
很多新手一上来就被这三个名字搞晕了。其实没那么复杂,我给大家捋一捋。
3.2.1 Modbus RTU —— 最常用的串口模式
RTU模式用二进制传输,数据紧凑,效率高。一个报文里,8位数据直接打包发送。我在项目中90%的串口Modbus通讯用的都是RTU模式。
RTU的特点:
- 数据格式:1个起始位 + 8个数据位 + 1个停止位(常用),无校验或奇偶校验
- 报文紧凑,同样波特率下传输效率最高
- 必须严格计算CRC16校验,错一个字节整个报文就废了
避坑指南:我曾经在一个项目里,RTU报文总是丢包。查了两天,最后发现是RS-485的收发切换时间没控制好。RTU模式下,报文之间必须有3.5个字符时间的静默间隔,否则从站会把两个报文当成一个来处理。这个细节,很多手册上写得不清楚,但实际调试时特别要命。
3.2.2 Modbus ASCII —— 可读性优先
ASCII模式把每个字节拆成两个ASCII字符发送。比如0x1A,RTU直接发一个字节,ASCII要发'1'和'A'两个字符。效率低了一半,但好处是人眼能直接看报文内容。
ASCII的特点:
- 报文以冒号':'开头,以回车换行结束
- 校验用LRC(纵向冗余校验),计算简单
- 适合调试阶段,或者通讯链路质量很差的环境
说实话,我很少在生产环境中用ASCII模式。只有在实验室调试,或者和一些老旧的仪表通讯时才会用到。效率低是硬伤,你想想看,同样9600波特率,RTU能传的数据量,ASCII要花两倍时间。
3.2.3 Modbus TCP —— 拥抱以太网
Modbus TCP就是把Modbus报文封装在TCP/IP包里。去掉了CRC校验(因为TCP/IP底层已经做了),加了一个MBAP报文头。端口号固定用502。
TCP模式的优势很明显:
- 速度可以到100Mbps甚至更高
- 可以跨网段、跨路由器通讯
- 支持多主站同时访问(串口模式不行)
但要注意,Modbus TCP本质上还是主从模式。虽然物理上可以多主站,但应用层上,从站还是被动响应。我见过有人把Modbus TCP当成实时以太网用,结果丢数据了——Modbus TCP没有实时性保证,它只是个请求-响应协议。
我的建议:如果通讯距离在1000米以内,对实时性要求不高,用RTU串口最经济。如果距离远、节点多、或者需要接入上位机网络,用Modbus TCP。ASCII模式?除非你是在做调试工具,否则尽量别用。
3.3 物理层与协议栈:从电平到报文
嗯,这里要注意。Modbus协议本身不定义物理层,但实际应用中,物理层的选择直接决定了通讯的成败。
3.3.1 串口物理层:RS-232 vs RS-485
| 参数 | RS-232 | RS-485 |
|---|---|---|
| 传输方式 | 单端,非平衡 | 差分,平衡 |
| 最大距离 | 约15米 | 约1200米 |
| 节点数 | 1对1 | 最多32个(标准),可扩展 |
| 抗干扰 | 差 | 强 |
| 典型应用 | 近距离调试、编程口 | 远程IO、现场总线 |
我在现场调试时,最怕看到有人用RS-232拉100米线。信号早就衰减得不成样子了。RS-485才是工业现场的正确选择。记住一个口诀:232点对点,485能组网;232短距离,485跑得远。
3.3.2 协议栈结构
Modbus的协议栈其实很薄,不像TCP/IP那样七层八层的。它就这么几层:
应用层:Modbus应用协议(功能码 + 数据)
表示层:RTU/ASCII/TCP编码
传输层:TCP(仅Modbus TCP)或 无(串口模式)
网络层:IP(仅Modbus TCP)或 无(串口模式)
数据链路层:串口帧(RTU/ASCII)或 以太网帧
物理层:RS-232/RS-485 或 以太网PHY
你看,串口模式下,Modbus直接跑在物理层上面,没有网络层和传输层。这也是它实时性好的原因——协议栈短,延迟低。但代价就是不能跨网段,不能路由。
重要提醒:Modbus RTU的报文帧有严格的时间约束。两个字节之间的间隔不能超过1.5个字符时间,否则从站会认为报文结束了。这个时间在9600波特率下大约是1.5ms。如果你的程序处理不过来,就会频繁出现「帧错误」。我曾经在一个项目里用单片机软件模拟Modbus从站,就是因为中断响应不及时,导致帧间隔超时,折腾了好几天才找到原因。
3.4 一个简单的RTU报文实例
光说不练假把式。我们来看一个实际的RTU报文:
请求报文(主站→从站):
01 03 00 00 00 02 C4 0B
解析一下:
- 01:从站地址,1号从站
- 03:功能码,读取保持寄存器
- 00 00:起始地址,从0号寄存器开始
- 00 02:读取数量,读2个寄存器
- C4 0B:CRC16校验,低字节在前
响应报文(从站→主站):
01 03 04 00 0A 00 14 3A 1F
解析:
- 01:从站地址
- 03:功能码回显
- 04:数据字节数,4个字节
- 00 0A:第一个寄存器值,10(十进制)
- 00 14:第二个寄存器值,20(十进制)
- 3A 1F:CRC16校验
你看,就这么简单。主站问一句,从站答一句。没有握手,没有确认,没有重传。这就是Modbus的哲学——简单到极致。
调试技巧:我习惯用串口助手先抓一下报文,看看主站发了什么,从站回了什么。如果从站不回,或者回的是异常码(功能码最高位置1),那就说明请求有问题。比如上面那个例子,如果从站回的是01 83 02 C0 F1,那83就表示「03功能码异常」,02表示「非法数据地址」。这种调试方法,比看代码快多了。
3.5 小结
Modbus协议入门,说白了就是搞清楚三件事:
- 它怎么来的——40多年的老协议,简单可靠,至今活跃
- 三种变体怎么选——RTU最常用,TCP上网络,ASCII少用
- 物理层怎么搭——RS-485是王道,注意帧间隔和终端电阻
下一章我们会深入Modbus的功能码和数据模型。到时候我会拿一个真实的远程IO模块案例,手把手教大家怎么读写寄存器。嗯,那个案例里有个坑,我当年踩过,到时候跟大家细说。