Modbus 是一种广泛使用的通信协议,主要用于工业自动化系统中的设备间通信。Modbus 的校验方法主要包括 CRC 和 LRC,CRC 和 LRC 校验确保了在工业环境中数据传输的可靠性。对于实际应用,可以利用各种库和工具来计算 CRC 和 LRC 校验码,以便进行数据验证。
Modbus 协议主要有两种通信方式:RTU(Remote Terminal Unit)模式和 ASCII(American Standard Code for Information Interchange)模式。
Modbus 数据帧结构
- Modbus RTU:
[ 地址 ][ 功能码 ][ 数据 ][ CRC-16 ]
- Modbus ASCII:
[ 起始字符 ][ 地址 ][ 功能码 ][ 数据 ][ LRC ][ 结束字符 ]
Modbus RTU CRC 校验
- 在 Modbus RTU 模式中,**CRC(循环冗余校验)**用作数据校验。CRC(循环冗余校验码)是一种常用的错误检测技术,广泛应用于数据通信和存储中。它能有效地检测数据在传输或存储过程中是否发生了错误。
CRC-16 校验概述
Modbus RTU 使用 CRC-16 校验码来验证数据的完整性。CRC-16 校验码基于一个 16 位的生成多项式 0x8005(其反向形式为 0xA001,常用),具体算法如下:
- CRC-16 计算步骤
- 初始化 CRC 寄存器:
- 初始化 CRC 寄存器为 0xFFFF(全 1)。
- 数据处理:
- 对于数据帧中的每个字节:
- 将数据字节与 CRC 寄存器当前值进行异或运算。
- 对结果进行 8 次位移操作,每次位移后,如果最低位为 1,则与生成多项式 0x8005 进行异或操作。
- 计算 CRC 校验码:
- 处理完所有字节后,CRC 寄存器的值即为 CRC 校验码。
CRC-16 计算详细示例
假设数据帧为:0x01 0x03 0x02 0xFF 0xFF
-
初始化 CRC:
- CRC 寄存器:0xFFFF
-
逐字节计算 CRC:
字节 0x01:
CRC = 0xFFFF ^ 0x01 = 0xFFFE
执行 8 次移位和异或操作:
结果变为:0xE0E0字节 0x03:
CRC = 0xE0E0 ^ 0x03 = 0xE0E3
执行 8 次移位和异或操作:
结果变为:0xD8D8字节 0x02:
CRC = 0xD8D8 ^ 0x02 = 0xD8DA
执行 8 次移位和异或操作:
结果变为:0xD4D4字节 0xFF:
CRC = 0xD4D4 ^ 0xFF = 0xD4CB
执行 8 次移位和异或操作:
结果变为:0x8F8F字节 0xFF(最后一个字节):
CRC = 0x8F8F ^ 0xFF = 0x8F90
执行 8 次移位和异或操作:
结果变为:0xD48E
最终 CRC 校验码:0xD48E -
附加 CRC 校验码:
- 数据帧末尾附加 CRC 校验码:0x8ED4(低字节在前,高字节在后)
Modbus ASCII LRC 校验
Modbus ASCII 模式使用 LRC(纵向冗余校验) 来确保数据的完整性。LRC 是通过对数据帧中的所有字节进行异或操作后取反得到的。
LRC 计算步骤
- 初始化 LRC 值:
- 初始化为 0x00。
- 逐字节计算 LRC:
- 对数据帧中的每个字节进行异或操作。
- 计算 LRC 校验码:
- 对结果进行按位取反,得到 LRC 校验码。
LRC 计算详细示例
假设数据帧为 01 03 02 FF FF(不包括起始字符和结束字符)
-
初始化 LRC:
- LRC = 0x00
-
逐字节计算 LRC:
字节 0x01:
LRC = 0x00 ^ 0x01 = 0x01字节 0x03:
LRC = 0x01 ^ 0x03 = 0x02字节 0x02:
LRC = 0x02 ^ 0x02 = 0x00字节 0xFF:
LRC = 0x00 ^ 0xFF = 0xFF字节 0xFF(最后一个字节):
LRC = 0xFF ^ 0xFF = 0x00 -
计算 LRC 校验码:
- LRC 校验码 = 按位取反 0x00 = 0xFF
-
附加 LRC 校验码:
- 数据帧末尾附加 LRC 校验码:0xFF