CRC校验的算法实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
CRC校验的算法实现
一、CRC简介
CRC基于多项式的编码技术。
在多项式编码中,将信息位串看成阶次为从X^k-1到X^0的信息多项式M(x)的系数序列,在计算CRC码时,发送方和接收方必须采用同一个生成多项式G(x),G(x)的阶次应该低于M(x),且最高和最低阶的系数为1。
根据发送端要传送的k位二进制码序列,可以以一定的规则产生一个r位检验码(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,为传送多项式T(x),最后将其发送出去。
产生CRC码的方法是:
以16位CRC码产生规则为例:先将要发送的二进制序列数左移16位(即乘以2的16 次方后)后,再除以生成多项式(这里采用的是模2运算法则,即多项式除法中采用不带借位的减法运算,运算等同于异或运算。
),最后所得到的余数就是CRC码。
任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。
例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。
二、检验原理
因为接收端接收到的传送多项式T(x)一定能被生成多项式G(x)模2整除,所以可用来判断传输过程是否出现错码。
接收端有两种处理方式:1、计算k位序列的CRC码,与接收到的CRC比较,一致则接收正确。
2、计算整个k+r 位的CRC码,若为0,则接收正确。
三、算法实现
这里采用 CRC-CCITT 多项式G(X) = X16 + X12 + X5 + 1,多项式为0x11021,因为第一位固定位1可省略,故C语言编程时,参与计算的为0x1021。
当按位计算CRC时,例如计算二进制序列为1001 1010 1010 1111时,将二进制序列数左移16位,即为1001 1010 1010 1111 (0000 0000 0000 0000),实际上该二进制序列可拆
分为1000 0000 0000 0000 (0000 0000 0000 0000) + 000 0000 0000 0000 (0000 0000 0000 0000) + 00 0000 0000 0000 (0000 0000 0000 0000) + 1 0000 0000 0000 (0000 0000 0000 0000) + ……
共16个二进制分序列。
算法步骤为:
(1)对第一个二进制分序列求余数,竖式除法即为0x10000 ^ 0x11021运算,后面的0位保留;
(2)接着对第二个二进制分序列求余数,将第一步运算的余数*2 后再和第二个二进制分序列一起对0x11021 求余,这一步理解应该没什么问题。
如果该分序列为0,无需计算。
(3)对其余的二进制序列求余与上面两步相同。
(4)计算到最后一位时即为整个二进制序列的余数,即为CRC校验码。
四、源代码
unsigned char test[16] =
{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xf f};
unsigned char len = 16;
void main( void )
{
unsigned long temp = 0;
unsigned int crc;
unsigned char i;
unsigned char *ptr = test;
while( len-- )
{
for(i = 0x80; i != 0; i = i >> 1)
{
temp = temp * 2;
if((temp & 0x10000) != 0)
{
temp = temp ^ 0x11021;
}
if((*ptr & i) != 0)
{
temp = temp ^ (0x10000 ^ 0x11021);
}
}
ptr++;
}
crc = temp;
printf("0x%x ",crc);
}
五、补充
CRC算法既可以软件实现,也可以用硬件实现。
用硬件实现的移位反馈寄存器的逻辑图如下图。
编码、解码前将各寄存器初始化为"1",信息位随着时钟移入。
当信息位全部输入后,从寄存器组输出CRC结果。
具体步骤为:
a)寄存器组初始化为全"1"(0xFFFF)。
b)寄存器组向右移动一个字节。
c)刚移出的那个字节与数据字节进行异或运算,得出一个指向值表的索引。
d)索引所指的表值与寄存器组做异或运算。
e)数据指针加1,如果数据没有全部处理完,则重复步骤b。
f)寄存器组取反,得到CRC,附加在数据之后,低字节在前,高字节在后。
六、总结:
两种算法都为逐位运算,运算过程很容易理解,所占内存少,但缺点是比较耗时。