QQ扫一扫联系
CRC(循环冗余校验)原理
CRC 是一种基于多项式的错误检测方法。在 Modbus RTU 通信协议中,CRC 校验用于验证数据的完整性。发送方会根据数据内容计算出一个 CRC 值,并将其附加在数据帧的末尾发送。接收方使用相同的算法计算接收到的数据(不包括 CRC 字段本身)的 CRC 值,并与接收到的 CRC 值进行比较。如果两者相同,则认为数据传输正确;否则,数据可能在传输过程中出现错误。
CRC 计算涉及多项式除法。在 Modbus RTU 中,通常使用的多项式是
(对应的十六进制数为 0xA001)。计算过程是将数据看作一个多项式的系数序列,然后与 CRC 多项式进行模 2 除法运算。不同写法导致结果不同的原因
数据长度处理不同:在计算 CRC 时,对于数据长度的理解和处理可能不同。例如,有些实现可能会将整个数据帧(包括功能码、地址等所有字段)的长度固定为某个值进行计算,而有些可能会根据实际发送或接收的数据长度动态调整计算范围。如果数据长度不一致,那么计算出来的 CRC 结果也会不同。
数据预处理不同:在进行 CRC 计算之前,可能需要对数据进行一些预处理。比如,有些实现可能会对数据进行补零操作,以满足 CRC 计算算法的要求,而有些可能不会进行这样的操作。或者对于一些特殊字符(如起始字符、停止字符等)的处理方式不同,也会导致 CRC 计算结果的差异。
字节顺序不同:CRC 计算可能涉及多个字节的数据。一种常见的错误是字节顺序处理不当。例如,有些实现可能是先处理高位字节,而有些可能先处理低位字节。在 Modbus RTU 中,数据字节的顺序是很重要的。如果在计算 CRC 时字节顺序不一致,就会导致不同的结果。
初始值设置不同:CRC 计算通常需要一个初始值。在标准的 Modbus RTU CRC 计算中,初始值通常是 0xFFFF。但是,如果不同的写法采用了不同的初始值,比如 0x0000 或者其他值,那么计算出来的 CRC 结果肯定是不同的。
计算过程中的数据类型和运算精度差异:CRC 计算涉及位运算和字节操作。不同的写法可能在数据类型选择上有差异,例如,有些可能使用无符号字符型(unsigned char
)来处理每个字节,而有些可能使用整数类型(int
)。这会导致在进行位移操作和加法等运算时产生不同的中间结果,从而影响最终的 CRC 校验值。
算法实现细节差异
数据范围和处理方式差异
示例说明
如果初始值设为 0x0000,按照相同的计算步骤,由于初始值不同,在后续与字节相加以及进行模 2 除法的过程中,所有的中间结果都会不同。最终计算出来的 CRC 校验值会是一个错误的值,与正确的 0x85CC 不同。
按照标准的 CRC - 16/Modbus 算法,先将初始值设为 0xFFFF。然后对于每个字节,从高位到低位依次进行以下操作:将当前 CRC 值的高字节左移 8 位,与当前字节相加,得到一个新的临时值。然后用这个临时值与多项式 0xA001 进行模 2 除法(实际上是通过一系列的位移和异或操作来实现),更新 CRC 值。
经过完整的计算后,得到的 CRC 校验值应该是 0x85CC。
假设我们有一个简单的 Modbus RTU 数据帧,包含地址(1 字节)、功能码(1 字节)和数据(2 字节),总共 4 字节的数据序列,设为 {0x01, 0x03, 0x12, 0x34}
。
正确的 CRC 计算(初始值为 0xFFFF)
错误的 CRC 计算(初始值为 0x0000)
所以,在进行 Modbus RTU 的 CRC 校验计算时,一定要严格按照协议规定的算法细节和数据处理方式来进行,以确保计算结果的准确性。