4、Modbus ASCII协议帧结构:起始/结束标记、LRC校验、与RTU模式的区别与转换

好,咱们接着聊Modbus。上一章我把RTU模式扒了个底朝天,这一章咱们来看看它的“亲兄弟”——ASCII模式。

说实话,我在现场摸爬滚打这么多年,用ASCII模式的项目其实不多。但每次遇到,都是些让人头疼的场景——比如无线数传电台、老旧的PLC系统,或者信号质量特别差的线路。这时候,ASCII模式反而成了救命稻草。

为什么会这样?你想想看,RTU用的是二进制传输,一个字节8个bit,对时序要求极高。而ASCII模式呢?它把每个字节拆成两个ASCII字符来发,虽然效率低了一半,但抗干扰能力确实强了不少。

4.1 ASCII模式的帧结构

先看一个典型的ASCII帧长什么样:

: 01 03 00 00 00 02 7B \r\n

嗯,是不是感觉比RTU多了些东西?我来拆开讲:

  • 起始标记:一个冒号 :(十六进制0x3A),告诉接收方“我要开始发数据了”
  • 地址码:2个ASCII字符,比如 01 表示从站地址1
  • 功能码:2个ASCII字符,比如 03 表示读保持寄存器
  • 数据区:N个ASCII字符对,每个字节拆成两个字符
  • LRC校验:2个ASCII字符,这是ASCII模式特有的校验方式
  • 结束标记:回车换行 \r\n(0x0D 0x0A)

关键区别:ASCII模式把每个二进制字节都“翻译”成了两个可打印的ASCII字符。比如RTU里的 0x1A,在ASCII里就变成了 '1''A' 这两个字符。

4.2 LRC校验——我踩过的坑

LRC,全称 Longitudinal Redundancy Check,纵向冗余校验。说白了,它比RTU的CRC简单得多。

计算规则

  1. 把地址码、功能码、数据区所有字节加起来(注意是二进制值,不是ASCII字符)
  2. 取和的低8位
  3. 计算补码(256 - 低8位)
  4. 结果转成两个ASCII字符

举个例子,还是上面那个报文:

地址: 0x01
功能码: 0x03
数据: 0x00 0x00 0x00 0x02

求和: 0x01 + 0x03 + 0x00 + 0x00 + 0x00 + 0x02 = 0x06
低8位: 0x06
补码: 256 - 6 = 250 = 0xFA

所以LRC = "FA"

我曾经踩过的坑:有一次调试一个温控系统,数据总是偶尔出错。我查了半天,最后发现是LRC计算时把起始冒号 : 也算进去了。记住,LRC只计算地址到数据区的部分,不包括起始和结束标记。

4.3 ASCII vs RTU:到底选哪个?

我整理了一张对比表,你一看就明白:

对比项 ASCII模式 RTU模式
字符编码 每个字节用2个ASCII字符 直接传二进制字节
传输效率 低(约50%开销) 高(几乎无开销)
校验方式 LRC(1字节) CRC(2字节)
帧间隔 无严格要求(靠 \r\n 分隔) 要求3.5字符时间间隔
抗干扰能力 强(只传可打印字符) 弱(二进制易受干扰)
适用场景 无线、低速、噪声大 有线、高速、稳定

我个人习惯是:能用RTU就用RTU,效率高、代码成熟。但如果你遇到以下情况,我建议切换到ASCII:

  • 用无线数传电台或GPRS模块,信号不稳定
  • 设备老旧,不支持严格的3.5字符帧间隔
  • 调试阶段,ASCII报文肉眼可读,方便排查

4.4 两种模式的互相转换

这个其实不难,核心就两步:

RTU → ASCII

  1. 把RTU帧的每个字节转成2个十六进制ASCII字符
  2. 去掉CRC,换成LRC
  3. 前面加冒号 :,后面加 \r\n

ASCII → RTU

  1. 去掉起始冒号和结束 \r\n
  2. 每两个ASCII字符转成一个二进制字节
  3. 去掉LRC,换成CRC

给你看个实际转换的例子:

RTU报文(十六进制):
01 03 00 00 00 02 C4 0B

转成ASCII报文:
: 01 03 00 00 00 02 FA \r\n

注意:RTU的CRC是 C4 0B,ASCII里换成了LRC FA

小技巧:我写转换工具时,习惯先判断报文第一个字符是不是冒号。如果是,按ASCII解析;如果不是,按RTU解析。这样程序就能自动识别模式,省去手动配置的麻烦。

4.5 抓包实战建议

用Wireshark或Modbus Poll抓ASCII报文时,有几点要注意:

  • ASCII模式在Wireshark里显示为 Modbus/ASCII,别选成RTU
  • 抓包时注意看起始冒号是否完整,有时候无线传输会丢包
  • LRC校验失败时,先检查是不是把 \r\n 也算进校验范围了

嗯,ASCII模式的内容差不多就这些。说白了,它就是RTU的“安全版”——牺牲效率换可靠性。下次你在现场遇到信号差、设备老的情况,不妨试试切到ASCII模式,说不定问题就迎刃而解了。