4、Modbus TCP/IP:Modbus TCP协议栈、与串行Modbus的区别

好,咱们今天聊聊Modbus TCP/IP。说实话,很多刚入行的朋友总觉得Modbus TCP就是把串口线换成了网线,其他都一样。嗯,这个想法其实挺危险的。我在现场调试的时候,就见过有人拿着串口版的代码直接往TCP上套,结果通讯死活不通,折腾了一整天。

Modbus TCP/IP,说白了就是Modbus协议跑在TCP/IP网络上。它和串行Modbus最大的区别,就是物理层和传输方式完全不同。咱们先看看它的协议栈长什么样。

4.1 Modbus TCP协议栈结构

Modbus TCP的协议栈,我习惯把它分成四层来看:

  • 物理层:以太网,RJ45接口,100Mbps或更高
  • 网络层/传输层:IP + TCP,负责寻址和可靠传输
  • 应用层:Modbus应用协议,也就是咱们熟悉的PDU(协议数据单元)
  • 封装层:MBAP报文头,这是Modbus TCP特有的东西

你想想看,串行Modbus用的是RS-232或RS-485,物理层就决定了它的通讯距离和速率。而Modbus TCP跑在以太网上,速率直接上到100M甚至千兆,距离也能通过交换机扩展。

这里我画了一张协议栈对比图,帮你直观理解:

Modbus TCP 协议栈 vs 串行Modbus 协议栈 Modbus TCP Modbus 应用层 (PDU) MBAP 报文头 (7字节) TCP 传输层 IP 网络层 以太网物理层 串行Modbus (RTU/ASCII) Modbus 应用层 (PDU) 地址 + 校验 (CRC/LRC) 串行链路层 (主从) RS-232 / RS-485 物理层 PDU相同 核心区别:TCP用MBAP头替代了串行的地址+校验,传输层由TCP保证可靠性

看到这张图,你应该能明白:PDU(协议数据单元)是完全一样的,区别在于封装方式。串行Modbus在PDU外面套了个地址和校验,而Modbus TCP套了个MBAP头。

4.2 MBAP报文头详解

MBAP,全称是Modbus Application Protocol Header。我刚开始接触的时候,总觉得这玩意儿就是多此一举。后来才明白,它解决了串行Modbus里一个很头疼的问题——报文边界识别。

MBAP头一共7个字节,结构如下:

字段 长度 说明
事务处理标识符 2字节 用于匹配请求和响应,客户端自己维护
协议标识符 2字节 固定为0x0000,表示Modbus协议
长度字段 2字节 后续数据的字节数(从单元标识符开始算)
单元标识符 1字节 相当于串行Modbus的从站地址

这里有个细节,我特别想提醒你:长度字段。它不包含MBAP头本身的7个字节,只算后面的数据。我在项目里就见过有人把这个算错了,导致报文解析全乱套。

关键点:事务处理标识符是客户端自己生成的,服务器响应时必须原样返回。这样客户端就能区分不同的请求,尤其是在并发通讯时特别有用。

4.3 与串行Modbus的核心区别

咱们一条一条说清楚。我列了个对比表,这样更直观:

对比项 串行Modbus (RTU/ASCII) Modbus TCP
物理层 RS-232 / RS-485 以太网 (RJ45)
通讯模式 主从模式,一主多从 客户端/服务器,支持多客户端
地址机制 从站地址 (1-247) 单元标识符 + IP地址
校验方式 CRC16 (RTU) 或 LRC (ASCII) 由TCP/IP协议栈保证
报文边界 3.5字符空闲时间 (RTU) 由TCP长度字段确定
传输速率 通常 9.6k - 115.2k bps 10/100/1000 Mbps
最大节点数 32 (RS-485 无中继) 理论上无限制

你看,最核心的区别其实就两点:

  1. 通讯模式变了:串行Modbus是严格的主从模式,只有主机能发起请求。而Modbus TCP是客户端/服务器模式,多个客户端可以同时访问同一个服务器。我在一个工厂改造项目里,就遇到过三台上位机同时读取同一台PLC的情况,用串行Modbus根本做不到,换成TCP就轻松解决了。
  2. 可靠性由TCP保证:串行Modbus需要自己算CRC校验,还得处理报文超时、重发这些事。Modbus TCP把这些脏活累活都交给TCP/IP协议栈了。TCP有确认重传、有序列号、有流量控制,比你自己写的重发机制靠谱多了。
⚠️ 避坑指南:我曾经在一个项目里,把Modbus TCP的端口号写错了。Modbus TCP的标准端口号是502,但有些设备厂商会改成其他端口。如果你发现通讯连不上,先检查一下端口号对不对。另外,502端口在Windows系统上需要管理员权限才能绑定,这个也容易踩坑。

4.4 报文格式对比

咱们直接看报文,这样最清楚。先看串行Modbus RTU的报文:

串行Modbus RTU 请求报文(读保持寄存器):
从站地址: 0x01
功能码:   0x03
起始地址: 0x00 0x6B
寄存器数: 0x00 0x03
CRC校验:  0x76 0x87

总共8个字节

再看Modbus TCP的报文:

Modbus TCP 请求报文(读保持寄存器):
MBAP头:
  事务标识: 0x00 0x01
  协议标识: 0x00 0x00
  长度:     0x00 0x06  (后面还有6个字节)
  单元标识: 0x01
PDU:
  功能码:   0x03
  起始地址: 0x00 0x6B
  寄存器数: 0x00 0x03

总共12个字节

你发现没有?PDU部分完全一样,就是外面套了个MBAP头。所以,如果你已经写过串行Modbus的代码,移植到TCP上其实不难——把地址和校验去掉,换成MBAP头就行。

💡 个人经验:我习惯在写Modbus TCP程序时,先封装一个MBAP头处理函数。这样不管是读还是写,只要调用这个函数把PDU包一下,就能直接通过socket发送了。代码复用性很高,也容易调试。

4.5 实际应用中的选择建议

说了这么多,到底该用串行Modbus还是Modbus TCP?我个人的建议是这样的:

  • 距离近、节点少、成本敏感:用串行Modbus。比如一个控制柜里的几个设备,用RS-485就够了,成本低,布线也简单。
  • 距离远、节点多、需要高速:用Modbus TCP。比如全厂级的DCS系统,几百个设备分布在各个车间,用以太网组网最合适。
  • 混合使用:很多项目其实是串行和TCP混用的。比如现场设备用RS-485组网,然后通过一个网关转成TCP,再接入上层系统。我在一个水处理项目里就这么干过,效果很好。

嗯,关于Modbus TCP/IP的内容,咱们就聊到这儿。记住,协议栈的结构、MBAP头的格式、以及与串行Modbus的区别,这三个点是你必须掌握的。下次调试的时候,如果遇到通讯问题,先看看报文格式对不对,再检查一下端口号和IP地址,大部分问题都能解决。