3、Modbus ASCII协议:ASCII帧格式、LRC校验计算、RTU与ASCII对比、ASCII模式调试技巧
好,咱们接着聊Modbus。上一节我们把RTU模式扒了个底朝天,这一节轮到它的“亲兄弟”——ASCII模式了。
说实话,我在现场摸爬滚打这么多年,用ASCII模式的时候确实比RTU少得多。但少归少,它有个RTU比不了的优势——可读性强。你想想看,RTU发出来的是一堆二进制数,用示波器抓出来全是乱码,而ASCII模式发的是人能看懂的字母和数字。调试的时候,这玩意儿能救命。
3.1 ASCII帧格式:长得像字符串的报文
ASCII模式的帧结构,说白了就是把RTU里的每个字节拆成两个ASCII字符来发送。比如0x1A,在RTU里直接发一个字节,在ASCII里就发字符'1'和'A'。
来看它的完整帧格式:
起始符 | 地址码 | 功能码 | 数据区 | LRC校验 | 结束符
':' | 2字节 | 2字节 | N字节 | 2字节 | CR+LF
每个字段都是可见的ASCII字符,这一点很关键。
各字段详解:
- 起始符:固定为冒号':'(0x3A)。这是帧开始的标志,设备收到冒号就知道新报文来了。
- 地址码:2个ASCII字符,比如从站地址0x11就发"11"。
- 功能码:2个ASCII字符,比如读保持寄存器0x03就发"03"。
- 数据区:长度可变,每个字节拆成两个字符。比如要发0x1234,就发"1234"。
- LRC校验:2个ASCII字符,计算方式下面细说。
- 结束符:回车CR(0x0D)+ 换行LF(0x0A)。
一个完整的例子:
读取地址为0x11的从站,起始地址0x006B,读取2个寄存器。
RTU模式发的是:11 03 00 6B 00 02 CRC16
ASCII模式发的是:: 11 03 00 6B 00 02 LRC CR LF
注意,这里的"11 03 00 6B 00 02"都是ASCII字符,不是二进制数。
3.2 LRC校验计算:比CRC简单多了
LRC(纵向冗余校验)的计算逻辑,比CRC16简单不止一个量级。我当年第一次手算LRC,五分钟就搞定了。
计算步骤:
- 把地址码、功能码、数据区的所有字节加起来(注意是字节,不是ASCII字符)。
- 丢掉进位,只保留低8位。
- 用256减去这个结果,得到LRC值。
- 把LRC值转成2个ASCII字符,放到帧里。
说白了就是三步:求和 → 取补 → 转ASCII。
举个实际例子:
还是上面那个报文,地址0x11,功能码0x03,数据区0x00 0x6B 0x00 0x02。
求和:0x11 + 0x03 + 0x00 + 0x6B + 0x00 + 0x02 = 0x81
取补:0x100 - 0x81 = 0x7F
转ASCII:'7' 和 'F'
所以LRC字段就是"7F"。
我的小技巧:
写代码的时候,LRC计算可以用一个循环搞定。我习惯这样写:
uint8_t calcLRC(uint8_t *data, uint16_t len) {
uint8_t sum = 0;
for(uint16_t i = 0; i < len; i++) {
sum += data[i];
}
return (uint8_t)(0x100 - sum);
}
注意,这个函数计算的是字节和的补码,不是直接取反。
3.3 RTU与ASCII对比:各有各的活法
这两个模式,我打个比方你就明白了:RTU像快递员,送得快但包裹上全是编号;ASCII像邮递员,送得慢但地址写得清清楚楚。
| 对比项 | RTU模式 | ASCII模式 |
|---|---|---|
| 数据密度 | 高,一个字节传一个数据 | 低,一个字节拆成两个字符 |
| 传输效率 | 高,同样波特率下快一倍 | 低,只有RTU的一半 |
| 校验方式 | CRC16,计算复杂但检错强 | LRC,计算简单但检错弱 |
| 帧间隔 | 3.5字符时间,严格 | CR+LF,明确 |
| 可读性 | 差,全是二进制 | 好,全是可见字符 |
| 适用场景 | 高速、大数据量 | 调试、低速、人机交互 |
什么时候用ASCII? 我个人觉得,就两种情况:
- 调试阶段,想用串口助手直接看报文内容。
- 通信链路质量差,RTU的3.5字符间隔老是被打断。
注意:
ASCII模式虽然可读性好,但传输效率只有RTU的一半。同样9600波特率,RTU一秒能传100个报文,ASCII只能传50个。如果你对实时性有要求,老老实实用RTU。
3.4 ASCII模式调试技巧:实战出真知
调试ASCII模式,比RTU舒服多了。为什么?因为你能直接看到报文内容。
技巧一:用串口助手直接看
打开串口助手,设置好波特率、数据位、停止位,选ASCII显示模式。你看到的报文就是这样的:
:1103006B00027F0D0A
一眼就能看出:起始符是':',地址是11,功能码是03,数据是006B0002,校验是7F,结束是0D0A。
技巧二:手算LRC验证
我曾经在现场遇到过一个问题:PLC发过来的ASCII报文,从站就是不响应。我拿计算器一算LRC,发现PLC算错了。这就是ASCII模式的好处——你可以拿笔算。
技巧三:注意字符大小写
Modbus ASCII标准里,十六进制字符A-F用大写。但有些设备不讲究,小写也认。我建议你统一用大写,省得踩坑。
技巧四:帧结束符不能省
ASCII模式靠CR+LF判断帧结束,不像RTU靠时间间隔。如果你漏发了结束符,从站会一直等,等到超时。
调试口诀:
冒号开头CRLF结尾,中间全是可见字符。
LRC校验算补码,大写字母最稳妥。
嗯,ASCII模式的内容就这些。说白了它就是RTU的“慢速可读版”,适合调试和低速场景。下一节我们讲Modbus TCP,那又是另一番天地了。