1.CRC16函数
1.1.输入输出数据类型
输入指令数据类型为uint8_t * ,数据长度根据指令长度减去两个CRC校验的字节。
生成的CRC校验码为uint16_t,Modbus校验码记得拆分高低8位并交换前后顺序,MSB-LSB则不需要交换位置。
1.2.函数详情
具体涉及到每一位的运算,不必过多纠结,也不用记住,除非是干编解码这一行的。
uint16_t CRC_Calculate(uint8_t *orderWithoutCrc, uint8_t length){
uint16_t crc_reg = 0xFFFF;
for(int i=0;i<length;i++){
crc_reg ^= orderWithoutCrc[i];
for(int j=0;j<8;j++){
uint8_t tmp = crc_reg & 0x0001;
crc_reg >>= 1;
if (tmp){
crc_reg ^= 0xA001;
}
}
}
return crc_reg;
}
2.Modbus CRC-16判断函数
2.1. 输入输出数据类型描述
输入指令缓冲变量,输出uint8_t类型为仿布尔的SET(1)或RESET(0)
2.2.CRC16判断函数
uint8_t ModbusRecvCrcJudge(uint8_t *rxBuffer){
uint8_t *rxBufferWithCrc;
uint16_t crcTemp = 0x0000;
uint8_t crc1 = 0x00;
uint8_t crc2 = 0x00;
rxBufferWithCrc = rxBuffer;
//指针对应到地址,改动需要更换地址并复制内容
//Temp is a short-time var, not a const.
crcTemp = CRC_Calculate(rxBufferWithCrc, 6);
crc2 = (uint8_t)((crcTemp >> 8) & 0xFF) ;
crc1 = (uint8_t)(crcTemp & 0xFF);
if((crc1 == rxBuffer[6])&&(crc2 == rxBuffer[7])){
return SET;
}else{
return RESET;
}
}
2.3.实测bug提示
如果先给低8位再给高8位会出现两个值都等于低8位的情况,gpt差点把我带沟里去了(硬件没问题)。
3.总结
先苦后甜,把复杂的问题简单化是上上之策。