C#CRC16 Modbus 效验算法
程序员文章站
2024-02-01 19:23:22
CRC校验(循环冗余校验)小知识 CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也 ......
crc校验(循环冗余校验)小知识
crc即循环冗余校验码(cyclic redundancy check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(crc)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。
crc算法参数模型解释:
name:参数模型名称。
width:宽度,即crc比特数。
poly:生成项的简写,以16进制表示。例如:crc-32即是0x04c11db7,忽略了最高位的"1",即完整的生成项是0x104c11db7。
init:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。
refin:待测数据的每个字节是否按位反转,true或false。
refout:在计算后之后,异或输出之前,整个数据是否按位反转,true或false。
xorout:计算结果与此参数异或后得到最终的crc值。
crc16 modbus主要实现方法
/// <summary> /// crc16_modbus效验 /// </summary> /// <param name="bytedata">要进行计算的字节数组</param> /// <returns>计算后的数组</returns> public static byte[] tomodbus(byte[] bytedata) { byte[] crc = new byte[2]; uint16 wcrc = 0xffff; for (int i = 0; i < bytedata.length; i++) { wcrc ^= convert.touint16(bytedata[i]); for (int j = 0; j < 8; j++) { if ((wcrc & 0x0001) == 1) { wcrc >>= 1; wcrc ^= 0xa001;//异或多项式 } else { wcrc >>= 1; } } } crc[1] = (byte)((wcrc & 0xff00) >> 8);//高位在后 crc[0] = (byte)(wcrc & 0x00ff); //低位在前 return crc; }
/// <summary> /// crc16_modbus效验 /// </summary> /// <param name="bytedata">要进行计算的字节数组</param> /// <param name="bytelength">长度</param> /// <returns>计算后的数组</returns> public static byte[] tomodbus(byte[] bytedata, int bytelength) { byte[] crc = new byte[2]; uint16 wcrc = 0xffff; for (int i = 0; i < bytelength; i++) { wcrc ^= convert.touint16(bytedata[i]); for (int j = 0; j < 8; j++) { if ((wcrc & 0x0001) == 1) { wcrc >>= 1; wcrc ^= 0xa001;//异或多项式 } else { wcrc >>= 1; } } } crc[1] = (byte)((wcrc & 0xff00) >> 8);//高位在后 crc[0] = (byte)(wcrc & 0x00ff); //低位在前 return crc; }
crc16 modbus(lsb-msb)通讯中校验字节格式为lsb-msb,扩展方法可以忽略。
注意:modbus 通讯中校验字节格式为lsb-msb,即低字节在前。
/// <summary> /// crc16_lsb-msb效验 /// </summary> /// <param name="bytedata">要进行计算的字节数组</param> /// <returns>计算后的数组</returns> public static byte[] tomsblsb(byte[] bytedata) { byte[] crc = new byte[2]; byte[] crcswtich = new byte[2]; crc = tomodbus(bytedata); crcswtich[0] = crc[1]; //高位在后 crcswtich[1] = crc[0]; //低位在前 return crcswtich; }
常见crc参数模型如下:
crc算法名称 | 多项式公式 | 宽度 | 多项式 | 初始值 | 结果异或值 | 输入值反转 | 输出值反转 |
---|---|---|---|---|---|---|---|
crc-4/itu | x4 + x + 1 | 4 | 03 | 00 | 00 | true | true |
crc-5/epc | x4 + x3 + 1 | 5 | 09 | 09 | 00 | false | false |
crc-5/itu | x5 + x4 + x2 + 1 | 5 | 15 | 00 | 00 | true | true |
crc-5/usb | x5 + x2 + 1 | 5 | 05 | 1f | 1f | true | true |
crc-6/itu | x6 + x + 1 | 6 | 03 | 00 | 00 | true | true |
crc-7/mmc | x7 + x3 + 1 | 7 | 09 | 00 | 00 | false | false |
crc-8 | x8 + x2 + x + 1 | 8 | 07 | 00 | 00 | false | false |
crc-8/itu | x8 + x2 + x + 1 | 8 | 07 | 00 | 55 | false | false |
crc-8/rohc | x8 + x2 + x + 1 | 8 | 07 | ff | 00 | true | true |
crc-8/maxim | x8 + x5 + x4 + 1 | 8 | 31 | 00 | 00 | true | true |
crc-16/ibm | x6 + x5 + x2 + 1 | 16 | 8005 | 0000 | 0000 | true | true |
crc-16/maxim | x6 + x5 + x2 + 1 | 16 | 8005 | 0000 | ffff | true | true |
crc-16/usb | x6 + x5 + x2 + 1 | 16 | 8005 | ffff | ffff | true | true |
crc-16/modbus | x6 + x5 + x2 + 1 | 16 | 8005 | ffff | 0000 | true | true |
crc-16/ccitt | x6 + x2 + x5 + 1 | 16 | 1021 | 0000 | 0000 | true | true |
crc-16/ccitt-false | x6 + x2 + x5 + 1 | 16 | 1021 | ffff | 0000 | false | false |
crc-16/x5 | x6 + x2 + x5 + 1 | 16 | 1021 | ffff | ffff | true | true |
crc-16/xmodem | x6 + x2 + x5 + 1 | 16 | 1021 | 0000 | 0000 | false | false |
crc-16/dnp | x6 + x3 + x2 + x1 + x0 + x8 + x6 + x5 + x2 + 1 | 16 | 3d65 | 0000 | ffff | true | true |
crc-32 | x2 + x6 + x3 + x2 + x6 + x2 + x1 + x0 + x8 + x7 + x5 + x4 + x2 + x + 1 | 32 | 04c11db7 | ffffffff | ffffffff | true | true |
crc-32/mpeg-2 | x32 + x6 + x3 + x2 + x6 + x2 + x1 + x0 + x8 + x7 + x5 + x4 + x2 + x + 1 | 32 | 04c11db7 | ffffffff | 00000000 | false | false |