前情回顾
在之前的ModBus RTU教程中,我们已经介绍了ModBus RTU的相关定义与通讯协议说明,本期将会介绍ModBus ASCII,本期内容在汇川PLC的串口通讯上使用不到,但Socket部分可能涉及,大家根据工作需要进行学习即可。
什么是Modbus ASCII?
前面我们提到,在Modbus出现的早期变体当中,其中有一个就是ModBus ASCII,相比较于RTU的2进制传输,ASCII使用的是文本传输,整个数据包都是可打印字符。如何理解所谓的文本传输呢?首先我们需要理解什么是ASCII?
ASCII
ASCII是一种字符编码标准,用于在计算机中表示文本字符。ASCII(美国信息交换标准代码)使用7位二进制数来表示128个字符,包括英文字母、数字、标点符号和一些特殊字符。ASCII编码最初由美国国家标准学会于1963年制定,1967年第一次发布,最后一次更新是在1986年,它包含了33个控制字符(具有某些特殊功能但是无法显示的字符)和95个可显示字符;
ASCII码 是 American Standard Code for Information Interchange 的缩写,而不是ASCⅡ(罗马数字2),有很多人在这个地方产生误解;
ASCII码表
了解了什么是ASCII码,那么就清楚了文本传输,也就是Modbus ASCII传输的内容是ASCII码,也就是二进制编码以后的内容。Modbus ASCII 使用可读的 ASCII 字符来表示消息,这使得它与二进制格式的 Modbus RTU(Remote Terminal Unit)相比,具有某些特定的优点和缺点。
特点
-
消息格式:
- Modbus ASCII 的每条消息以冒号
:
开头,并以换行符CRLF
结尾。 - 每个字节的数据以两个 ASCII 字符的十六进制形式表示。
- 例如,一个字节的数据
0x5A
在 Modbus ASCII 中表示为5A
。(代表大写字母 Z)
- Modbus ASCII 的每条消息以冒号
-
通信速度:
- Modbus ASCII 的通信速度通常比 Modbus RTU 慢,因为每个字节需要两个 ASCII 字符来表示。
- 由于其字符表示形式,它在传输过程中需要更多的带宽。
-
易于调试:
- 由于 Modbus ASCII 消息是人类可读的,它们比 Modbus RTU 更容易调试和分析。
-
应用场景:
- Modbus ASCII 常用于需要通过电话线或无线电进行通信的系统,这些系统可能会受益于其易读性和错误检测能力。
消息结构
Modbus ASCII 消息包括以下几个部分:
- 起始字符:每条消息以冒号
:
开头。 - 地址域:表示目标设备的地址,通常为 2 个 ASCII 字符的十六进制值。
- 功能码:表示请求的操作类型,通常为 2 个 ASCII 字符的十六进制值。
- 数据域:包含与请求或响应相关的数据,长度可变,每个字节用 2 个 ASCII 字符表示。
- 校验和 (LRC, Longitudinal Redundancy Check):用于错误检测,通常为 2 个 ASCII 字符的十六进制值。
- 结束字符:每条消息以回车符和换行符 (CRLF) 结尾。
LRC校验
LRC(Longitudinal Redundancy Check)校验是一种用于检测数据传输错误的校验方法。它在 Modbus ASCII 通信协议中使用,用于确保消息在传输过程中没有被篡改或损坏。
LRC 校验的工作原理
LRC 校验通过对消息中的每个字节进行累加,然后取结果的二进制补码(即取反加一),得到一个校验和字节。这个校验和字节会附加到消息的末尾,接收方在收到消息后会进行同样的计算,以验证消息的完整性。
计算 LRC 校验的步骤
-
初始化 LRC 值:
- 将 LRC 值初始化为 0。
-
累加消息的每个字节:
- 对消息的每个字节进行累加(这里指的是消息的地址域、功能码和数据域,不包括起始字符冒号和结束字符 CRLF)。
-
取二进制补码:
- 将累加结果取二进制补码,即对结果取反加一(也可以通过将结果从 256 中减去来实现)。
计算示例
假设一条 Modbus ASCII 消息为 :010300010001FB\r\n
,我们需要计算其中的 LRC 校验值。步骤如下:
-
去掉起始和结束字符:仅考虑
010300010001
部分。 -
将每对 ASCII 字符转换为十六进制值:
01
-> 0x0103
-> 0x0300
-> 0x0001
-> 0x0100
-> 0x0001
-> 0x01
-
累加这些值:
- 累加结果:0x01 + 0x03 + 0x00 + 0x01 + 0x00 + 0x01 = 0x06
-
取反加一(计算补码):
- 0x06 的反码是 0xF9(取反),加一得到 0xFA。
-
LRC 校验值:
- 计算得到的 LRC 校验值是 0xFA。
因此,整个消息的 LRC 校验和是 FA
。完整的 Modbus ASCII 消息在计算校验时包括 LRC 字节:
:010300010001FA\r\n
验证 LRC 校验
接收方接收到消息后,会进行以下步骤:
- 从接收到的消息中提取数据部分(地址、功能码和数据),并包括接收到的 LRC 字节。
- 对这些字节进行累加,然后取反加一。
- 如果结果为零,说明消息未被篡改,校验通过;否则,校验失败。
原消息中是 FB,它正确吗?
肯定是不对的,因为
0x01 + 0x03 + 0x00 + 0x01 + 0x00 + 0x01 + 0xFB = 0x102
最低字节 0x02,不为 0,说明 FB 不满足 LRC 校验和的正确性。因此,正确的校验和应为 FA。
总结
LRC 校验是一种简单但有效的错误检测方法,通过累加消息中的每个字节并计算其补码,可以检测出在传输过程中发生的错误。Modbus ASCII 协议使用 LRC 校验来确保数据的完整性和可靠性。
例子
假设一个 Modbus 主站向地址为 01
的从站发送一个读保持寄存器的请求,读取寄存器地址为 0001
,数量为 0001
。这条 Modbus ASCII 消息可能看起来像这样:
:010300010001FA\r\n
:
- 起始字符01
- 目标从站地址03
- 功能码,表示读保持寄存器0001
- 起始寄存器地址0001
- 读取的寄存器数量FA
- 校验和\r\n
- 回车和换行符
如果全部用16进制表达:
3A010300010001FA0D0A
总之,Modbus ASCII 是一种通过使用 ASCII 字符进行数据传输的 Modbus 协议版本,适用于某些特定的应用场景,特别是需要在长距离或噪声环境中通信时。