一、简介:
我用的是直接计算法,非查表法。直接计算更符合我的项目要求,我是使用在STM32单片机上的用的是KEIL。按道理说跟平台无关,整个用的是C语言编写。在网上也有很多对CRC的讲解,我这里就不班门弄斧了,我也是刚学的,很多网站教程都很详细的讲解了CRC的原理和方法,但是比较少有一个总的总结,在这里我只写我的实现过程,或许能帮到刚学习的朋友,顺便记录一下。
这里推荐一个挺不错的讲解网站看完网站的讲解,再看剩下的流程就明白了。
CRC32为例详细解析(菜鸟至老鸟进阶)
二、步骤:
需要计算的数据:data
POLY:多项式
INIT:初始值
XOROUT :结果异或值
1、对数据data倒置(跟第四步的倒置有区别)
这是是针对的每个字节,而不是整个数据,然后赋回给data
例如:
00101011,10110100,00100101,10000011
倒置:
11010100,00101101,10100100,11000001
2、data = data ^ 初始值 INIT
(一般是0xFFFFFFFF,或者0x00000000,也可以自定义)
3、这里就开始计算
判断data最高位为1还是0,
1:data = data^POLY
0:不处理
然后data左移一位再重复执行步骤3,直到得到一个等于或小于 多项式(其实就是按照数据长度一般都是移多少次,8bit:8次,32bit:32次)
4、输出结果处理
data = data ^ 结果异或值 XOROUT (一般是0xFFFFFFFF,或者0x00000000,也可以自定义)
5、倒置整个结果data,(跟第一步不同)
这个是倒置整个数据。
例如:
00101011,10110100,00100101,10000011
倒置:
11000001,10100100,00101101,11010100
6、得到的 最终数据就是 CRC32 的值
这里附上几个CRC校验的网站:
ip33.com
On-line CRC calculation and free library
步骤计算结果:
三、代码分享
1、这是需要用到的代码倒置函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* 功 能:倒置数据 :例如10110010,倒置后:01001101 参 数:datar:需倒置的数据 dlen:倒置数据的长度 8/16/32 返回值:倒置后的数据 */ unsigned int zRCR_BitReverse(unsigned int datar,unsigned char dlen) //倒序数据 8/16/32 { unsigned int Rvalue=0; unsigned char i; for(i=0;i<dlen;i++) //倒置数据 { Rvalue |=((datar>>i)&0x00000001); if(i>=(dlen-1)) break; Rvalue<<=1; } return Rvalue; } |
2、CRC计算函数(输入数据为8bit)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /* 功 能:计算CRC32的值 参 数:*data:需计算的数据 len:数据个数 repeat:是否接着上一次计算,0:开始新的一轮计算,1:接着上次计算 返回值:CRC32的值 */ unsinged int zCRC_Value; unsigned int zCRC_GetCRC(unsigned char *data,unsigned int len,unsigned char repeat) { unsigned int i; unsigned int value_temp; if(repeat == 0) //是否继续上次的数据校验 zCRC_Value = 0XFFFFFFFF;//zCRC_State.zCRC_InitValue; while(len !=0) { //开启输入数据反转 //1、倒置数据,单独倒置每个Byte数据,非整个数据倒置 value_temp = 0; value_temp |= (zRCR_BitReverse(((*data)&0xFF),8)); value_temp <<=24; // 将数据移动最高位 data++; //2、数据与初始值求或 zCRC_Value ^= value_temp; for(i=0;i<8;i++) { if(zCRC_State.zCRC_Value&0x80000000) { zCRC_Value <<=1; zCRC_Value ^=0x4C11DB7; } else zCRC_Value <<=1; } len--; } return zRCR_BitReverse(zCRC_Value^0XFFFFFFFF,32); } |
2、CRC计算函数(输入数据为32bit)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | unsinged int zCRC_Value; unsigned int zCRC_GetCRC(unsigned int *data,unsigned int len,unsigned char repeat) { unsigned int i; unsigned int value_temp; if(repeat == 0) //是否继续上次的数据校验 zCRC_Value = 0XFFFFFFFF; while(len !=0) { //1、倒置数据,单独倒置每个Byte数据,非整个数据倒置:例如:00100101,10000011倒置过来>> 10100100,11000001 value_temp = 0; for(i=0;i<32;)// { //先将数据右移i位取1Byte,将二进制倒置一下,再往左移i位,保存value_temp value_temp |= (zRCR_BitReverse(((*data>>i)&0xFF),8)<<i); i+=8;//i每次进位8bit,1Byte } data++; //2、数据与初始值求或 zCRC_State.zCRC_Value ^= value_temp; for(i=0;i<32;i++) { if(zzCRC_Value&0x80000000) { zCRC_Value <<=1; zCRC_Value ^=0x4C11DB7; } else zCRC_Value <<=1; } len--; } return zRCR_BitReverse(zCRC_Value^0XFFFFFFFF,32); } |