4. 协议层帧结构分析:RTU、ASCII与TCP报文格式

各位工程师朋友,咱们今天聊聊Modbus的帧结构。说实话,搞通信诊断这么多年,我见过太多人拿着示波器对着波形发呆——明明物理层没问题,数据就是解析不出来。问题出在哪?多半是协议层没搞明白。

我个人习惯把协议层比作“信封”。你写好了信(数据),总得知道怎么装进信封、贴什么邮票、写什么地址吧?Modbus的帧结构,就是这套规则。

4.1 RTU帧格式:最常用的“二进制信封”

RTU模式,说白了就是纯二进制传输。每个字节8位,效率高,速度快。我90%的项目都用它。

一个完整的RTU帧长这样:

| 地址码 | 功能码 | 数据区 | CRC校验 |
| 1字节  | 1字节  | N字节  | 2字节   |

地址码(1字节):范围0x00-0xF7。0x00是广播地址,所有从站都得收,但不回复。0xF8-0xFF保留,别乱用。我在现场见过有人把地址设成0xFF,结果从站死活不响应——嗯,地址冲突了。

功能码(1字节):告诉从站你要干啥。常用的就那几个:

功能码 含义 我常用的场景
0x01 读线圈 读取继电器状态
0x03 读保持寄存器 读取传感器数值
0x06 写单个寄存器 设定PID参数
0x10 写多个寄存器 批量下发配置

数据区(N字节):根据功能码不同,长度可变。比如读寄存器时,这里放起始地址和数量;写寄存器时,放地址、数量和具体数值。

CRC校验(2字节):这是RTU的“防伪标签”。算法是CRC-16/MODBUS,多项式0x8005。我建议你直接用现成的查表法,别自己手算——我当年手算过一次,算完发现少了个0,折腾了俩小时。

避坑指南:我曾经遇到一个案例,从站偶尔回复错误。查了半天,发现是CRC计算时高低字节顺序搞反了。RTU的CRC是低字节在前,高字节在后。这点很多新手会栽跟头。

4.2 ASCII帧格式:可读但低效的“文本信封”

ASCII模式,每个字节拆成两个ASCII字符发送。比如0x1A,发的是'1'和'A'(0x31、0x41)。好处是肉眼能看,坏处是效率砍半。

帧结构:

| 起始符 | 地址码 | 功能码 | 数据区 | LRC校验 | 结束符 |
| 1字符  | 2字符  | 2字符  | 2N字符 | 2字符   | 2字符  |

起始符:固定0x3A(':')。
结束符:0x0D 0x0A(回车换行)。
LRC校验:纵向冗余校验,比CRC简单多了。就是把所有字节加起来,取补码。

说实话,我现在很少用ASCII模式。只有在调试初期,或者跟一些老设备对接时才会碰到。有一次在化工厂,PLC死活连不上,我让现场把模式切到ASCII,用串口助手一看报文——原来是地址码发成了小写字母。ASCII模式下,地址码必须是大写十六进制字符。

我的建议:除非设备只支持ASCII,否则一律用RTU。ASCII的LRC校验太弱,抗干扰能力差。你想想看,工厂里电机一启动,电磁干扰上来,ASCII帧很容易被破坏。

4.3 TCP报文格式:没有校验的“网络信封”

Modbus TCP,说白了就是把RTU帧去掉CRC,套上TCP/IP的头。因为TCP本身已经保证了可靠传输,CRC就多余了。

报文结构:

| MBAP头 | 功能码 | 数据区 |
| 7字节  | 1字节  | N字节  |

MBAP头(7字节)

字段 长度 说明
事务标识符 2字节 用于匹配请求和响应
协议标识符 2字节 固定0x0000
长度 2字节 后续字节数
单元标识符 1字节 相当于RTU的地址码

这里有个坑:单元标识符在TCP里其实没啥用,因为TCP连接已经唯一确定了设备。但很多网关设备会用它来路由到背后的串口设备。我遇到过一台网关,单元标识符设成0xFF就转发,设成其他值就丢弃——折腾了我一上午才试出来。

注意:Modbus TCP的默认端口是502。很多IT管理员会封这个端口,觉得不安全。我建议你跟网络部门提前沟通好,或者改用端口映射。别等到现场才发现连不上。

4.4 三种帧格式对比

我整理了一张表,方便你快速对比:

特性 RTU ASCII TCP
传输效率 低(减半)
校验方式 CRC-16 LRC TCP校验
可读性
适用场景 串口通信 调试/老设备 以太网
帧间隔 3.5字符时间 1秒超时

4.5 帧结构知识体系图

下面这张图,是我自己总结的帧结构分析思路。你照着这个流程走,基本不会漏掉关键点。

Modbus帧结构分析流程 步骤1:确认物理层接口 步骤2:判断通信模式 RTU模式 ASCII模式 TCP模式 RTU帧结构 地址+功能+数据+CRC 注意3.5字符间隔 ASCII帧结构 起始+地址+功能+数据+LRC+结束 注意字符大小写 TCP帧结构 MBAP头+功能+数据 注意单元标识符 步骤3:校验验证(CRC/LRC/TCP)

这张图的核心逻辑很简单:先确认物理层,再选模式,然后按对应格式解析,最后验证校验。我每次排查通信故障,都是按这个顺序来。你照着做,至少能解决80%的问题。

调试小技巧:如果你手头没有专业分析仪,可以用串口助手抓原始数据。RTU模式下,看到连续两个字节跟前面数据对不上,那多半就是CRC。ASCII模式下,看到冒号开头、回车换行结尾,基本没跑。TCP的话,用Wireshark抓包,过滤条件设成"modbus"就行。

好了,帧结构这块就聊到这儿。记住一句话:协议层的问题,90%出在校验和地址上。下次你遇到通信故障,先别急着怀疑硬件,拿示波器或者抓包工具看看帧结构对不对。很多时候,问题就出在你以为“肯定没问题”的地方。


专注资料整理