一、简介:
我用的是直接计算法,非查表法。直接计算更符合我的项目要求,我是使用在STM32单片机上的用的是KEIL。按道理说跟平台无关,整个用的是C语言编写。在网上也有很多对CRC的讲解,我这里就不班门弄斧了,我也是刚学的,很多网站教程都很详细的讲解了CRC的原理和方法,但是比较少有一个总的总结,在这里我只写我的实现过程,或许能帮到刚学习的朋友,顺便记录一下。
这里推荐一个挺不错的讲解网站看完网站的讲解,再看剩下的流程就明白了。
二、步骤:
需要计算的数据: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校验的网站:
On-line CRC calculation and free library
步骤计算结果:
三、代码分享
1、这是需要用到的代码倒置函数
/*
功 能:倒置数据 :例如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)
/*
功 能:计算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)
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);
}