现在的CPU来说,基本上都在硬件上实现了CRC校验。
使用查表法从软件上来实现CRC-32的校验。
CRC还有一种反转的情况,实际上反转和不反转没有什么太大的区别,主要是需求和标准的不同。
CRC校验中的查表法是一种优化CRC计算的方法,通过预先生成一个CRC校验表(也称为查表),可以加快CRC校验的计算速度。
具体来说,CRC校验通常涉及到大量的位运算和异或操作,这些操作在传统的CRC计算方法中可能需要大量的时间来完成,尤其是对于较长的数据帧和复杂的CRC多项式。为了提高CRC计算的效率,可以采用查表法来加速计算过程。
查表法的基本思想是在CRC校验初始化阶段,预先计算生成一个CRC校验表,表中存储了不同数据字节值对应的CRC校验结果。在实际进行CRC校验时,只需要按照数据字节逐个查询表中对应的CRC校验结果,并根据预先计算好的表格进行异或操作,而不需要每次都重新计算CRC校验值。
查表法原理
如果我们要软件上实现CRC的话,要一位一位的做这些运算,效率是非常低的,所以我们就想能不能每8位计算一次,因为每个特定的数字与这个被除数的经过8次移位操作得到的异或结果都是相同的。
(1)为什么不每16位计算一次?
这样就要保存 2^16 个uint16_t类型的数据,一个表格就有128KB,这比很多单片机的Flash要大了
(2)每8位计算一次的理论依据是什么
我们知道CRC(0)=0,然后由前面分析出的特性,我们可以推导出这个公式: CRC(A+B)=CRC(A)+CRC(B)。
现在举个例子,假如我们想求CRC(0×abcdef12),他就可以等价于:
CRC(0×abcdef12)=CRC(0×ab000000)+CRC(0×00cdef12)=CRC(0×ab)+CRC(0×cd)+CRC(0×ef)+CRC(0×12)
假如我们定义一个8位的查表表格,这样我们就可以把本来每次要进行的32次移位和异或的运算缩短为了4次。
CRC32表格生成
经过前面的分析,我们知道,我们就是需要给uint8_t范围内(0~255)的每一个数做一下模二除法,然后将得到的结果保存到一个类型为uint8_t、大小为256的表格中。我们只需要判断CRC的最高位是否为1,若为0则将CRC左移一位,若为1则先将CRC左移1位,然后和多项式做异或运算。CRC32表格生成代码如下:
void GenerateTable(uint32_t polynomial){
for (int byte = 0; byte < 256; ++byte){
uint32_t crc = byte;
for (int bit = 32; bit > 0; --bit){
if (crc & 0x80000000){
crc = (crc << 1) ^ polynomial;
}else{
crc <<= 1;
}
}
crcTable[byte] = crc;
}
}
CRC查表代码实现
有了前面的表格,我们使用下面的函数就能计算长度为len的字符串msg的CRC32了,在循环中,将CRC的高八位所对应的数在CRC32表格中的结果与上次计算出来的CRC右移八位的结果进行异或,最后就得到了这个字符串的CRC结果了。
unsigned int calcMsgCRC(char *msg, unsigned int len){
unsigned long crc = 0;
for (int n = 0; n < len; n++) {
uint8_t c = msg[n] & 0xff;
crc = crcTable[(crc >> 24) ^ c] ^ (crc << 8);
}
return crc;
}
原文链接:https://blog.csdn.net/tilblackout/article/details/131198350