这一节说明一下数据传输中常用的CRC校验
所谓CRC校验,说白了就是对数据做下计算,然后把计算结果放到最后面
平时用的最多的算是CRC16
计算CRC
/** * @brief calculate CRC * @param *modbusdata: Source data address * @param length: data length * @param * @retval CRC16 Value * @example **/ int crc16_modbus(u8 *modbusdata, int length) { int i, j; int crc = 0xffff;//0xffff or 0 for (i = 0; i < length; i++) { crc ^= modbusdata[i]; for (j = 0; j < 8; j++) { if ((crc & 0x01) == 1) { crc = (crc >> 1) ^ 0xa001; } else { crc >>= 1; } } } return crc; }
判断接收的数据CRC是否正确
/** * @brief check CRC for data * @param *modbusdata: Read data address * @param length: Read data length * @param * @retval 1:CRC16 OK * @example **/ int crc16_flage(u8 *modbusdata, int length) { int Receive_CRC=0,calculation=0;
if(length<=2) { return 0; }
Receive_CRC = crc16_modbus(modbusdata, length-2); calculation = modbusdata[length-2]; calculation <<= 8; calculation += modbusdata[length-1]; if(calculation != Receive_CRC) { return 0; } return 1; }
我想发送 01 00 55 aa 数据
最终发送的数据
说明:
1.最后两位 F7 和 BE就是经过CRC16计算之后的数据;高位在前,低位在后
2.整个数据发给另一个设备以后,另一个设备用同样的方式计算 01 00 55 aa 的CRC16值
然后判断下自己计算的值是不是 F7,BE
/// <summary> /// calculate CRC /// </summary> /// <param name="modbusdata">Source data address</param> /// <param name="length">data length</param> /// <returns></returns> private int crc16_modbus(byte[] modbusdata, int length) { int i, j; int crc = 0xffff; //0xffff or 0 try { for (i = 0; i < length; i++) { crc ^= modbusdata[i]&0xff; for (j = 0; j < 8; j++) { if ((crc & 0x01) == 1) { crc = (crc >> 1) ^ 0xa001; } else { crc >>= 1; } } } } catch (Exception) { throw; } return crc; }
/// <summary> /// /// </summary> /// <param name="modbusdata"></param> /// <param name="length"></param> /// <returns></returns> private int crc16_flage(byte[] modbusdata, int length) { int Receive_CRC = 0, calculation = 0;//接收到的CRC,计算的CRC if(length<=2) return 0; Receive_CRC = crc16_modbus(modbusdata, length-2); calculation = modbusdata[length -2]; calculation <<= 8; calculation += modbusdata[length-1]; if (calculation != Receive_CRC) { return 0; } return 1; }
注:对于上位机byte类型需要&0xff
大部分设备的CRC16计算方式,这个地方是 0xffff, 但是也有0的情况