4、Modbus ASCII帧结构:ASCII报文格式、LRC校验原理与计算、RTU与ASCII对比、何时选择ASCII
好,咱们今天聊聊Modbus的另一种传输模式——ASCII模式。
说实话,我在现场调试时,ASCII模式用得不算多。但每次用到它,都是因为RTU模式实在搞不定了。你想想看,一个系统里既有Modbus设备,又有各种打印终端、人机界面,字符集乱成一锅粥。这时候,ASCII模式就像个救火队员。
我个人习惯,把ASCII模式看作是RTU模式的“文本版”。它把每个字节拆成两个ASCII字符来发送。说白了,就是让数据变得“可读”了。
4.1 ASCII报文格式
ASCII帧的结构,跟RTU有点像,但细节上差别很大。咱们直接看格式:
起始符 | 地址码 | 功能码 | 数据区 | LRC校验码 | 结束符
':' | 1字节 | 1字节 | N字节 | 1字节 | CR+LF
嗯,这里要注意几个关键点:
- 起始符:固定是冒号
':'(0x3A)。这是帧开始的标志。 - 地址码、功能码、数据区:这些字段的内容,每个字节都要拆成两个ASCII字符发送。比如地址0x11,就发送字符'1'和'1'(即0x31, 0x31)。
- LRC校验码:1个字节,同样拆成两个ASCII字符。
- 结束符:回车换行(0x0D, 0x0A)。
举个例子,我要读取地址为0x11的设备的保持寄存器,起始地址0x0000,读取2个寄存器。RTU模式下报文是:11 03 00 00 00 02 CRC。换成ASCII模式,就变成了:
: 11 03 00 00 00 02 LRC \r\n
注意,这里的11、03等,都是ASCII字符。实际发送的是:3A 31 31 30 33 30 30 30 30 30 30 30 32 LRC 0D 0A。
我在项目中遇到过,有人把ASCII帧里的地址码直接当二进制发,结果设备死活不响应。记住,ASCII模式下,所有数据字段都是字符,不是原始字节。
4.2 LRC校验原理与计算
LRC,全称是纵向冗余校验。它比CRC简单得多,但防护能力也弱一些。
计算原理:从地址码开始,到数据区的最后一个字节,所有字节做累加,然后取补码。
公式很简单:
LRC = ( (累加和) 取反 ) + 1
或者更直接:LRC = 0x100 - (累加和 & 0xFF)
咱们手算一下刚才的例子:
地址码: 0x11
功能码: 0x03
起始地址高: 0x00
起始地址低: 0x00
寄存器数高: 0x00
寄存器数低: 0x02
累加和 = 0x11 + 0x03 + 0x00 + 0x00 + 0x00 + 0x02 = 0x16
LRC = 0x100 - 0x16 = 0xEA
所以,完整的ASCII帧发送内容为:: 11 03 00 00 00 02 EA \r\n。注意,EA也要拆成字符'E'和'A'发送。
unsigned char calcLRC(unsigned char *data, int len) {
unsigned char sum = 0;
for (int i = 0; i < len; i++) {
sum += data[i];
}
return (unsigned char)(0x100 - sum);
}
注意,len是从地址码开始到数据区结束的长度,不包括起始符和结束符。
4.3 RTU与ASCII对比
咱们直接上表格,一目了然:
| 对比项 | RTU模式 | ASCII模式 |
|---|---|---|
| 数据表示 | 二进制字节 | ASCII字符(每个字节拆成2个字符) |
| 帧长度 | 短(约是ASCII的一半) | 长(约是RTU的两倍) |
| 传输效率 | 高(同样波特率下,吞吐量更大) | 低(同样波特率下,吞吐量减半) |
| 校验方式 | CRC-16(2字节,强校验) | LRC(1字节,弱校验) |
| 帧间隔 | 3.5字符时间(严格) | 无严格时间要求(靠起始/结束符) |
| 可读性 | 差(全是二进制,人眼难辨) | 好(可以直接用串口助手看) |
| 适用场景 | 高速、可靠、工业现场 | 低速、调试、字符环境 |
你想想看,RTU模式为什么效率高?因为它每个字节就是实实在在的数据。而ASCII模式,发一个字节的数据,要占用两个字符的时间。同样9600波特率,RTU能发更多数据包。
但ASCII模式有个RTU比不了的优势——它不怕帧间隔。RTU要求帧内字节间隔不能超过3.5个字符时间,否则就认为帧结束了。这在一些实时性不高的系统里,很容易出问题。ASCII模式靠':'和CR+LF来定界,你就算中间停顿几秒钟,只要没收到结束符,设备就还在等。
4.4 何时选择ASCII
我个人经验,以下情况优先考虑ASCII模式:
- 调试阶段:用串口助手直接看报文,ASCII模式一目了然。我调试新设备时,经常先用ASCII模式把通信调通,再切回RTU。
- 与字符设备通信:比如某些老式打印机、字符终端、GPS接收器,它们只认ASCII字符。这时候用ASCII模式,兼容性最好。
- 通信链路不可靠:如果线路干扰大,或者中间有转发设备会随意插入字符,RTU的3.5字符时间间隔很容易被破坏。ASCII模式靠帧头帧尾定界,抗干扰能力强一些。
- 低速系统:比如1200波特率,RTU模式下的3.5字符时间间隔长达30多毫秒。如果主站轮询周期长,用ASCII模式反而更稳定。
嗯,ASCII模式的内容就这些。它不复杂,但细节容易踩坑。记住核心:数据拆成字符发,LRC校验要算对,帧头帧尾不能丢。下次你遇到RTU搞不定的情况,不妨试试ASCII模式。
公众号:蓝海资料掘金营,微信deep3321