crc原理总结

首先,很感谢http://wenku.baidu.com/view/fb791c0203d8ce2f006623f5.html作者的笔记。让我解除了对于crc的很多困惑。

        接下来我想整理一下这方面的知识。

1.算术上的除法:

120÷9=13 余 3,120是被除数,9是除数,13是商,3是余数。念作120除以9,或者9除120,或者9去除120!(除法的过程就不写了)  这个除法计算机当然会做,但是做起来很麻烦,因为减法有借位,很耗时间和指令! 所以,计算CRC也是除法,但是用XOR来代替减法

120÷9=13 余3,120是被除数,9是除数,13是商,3是余数。念作120除以9,或者9除120,或者9去除120!(除法的过程就不写了) 这个除法计算机当然会做,但是做麻烦,因为减法有借位,很耗时间和指令! 所以,计算CRC也是除法,但是用XOR来代替减法120÷9=13 余 3,120是被除数,9是除数,13是商,3是余数。念作120除以9,者9

除120,或者9去除120!(除法的过程就不写了) 这个除法计算机当然会做,但是做起来很麻烦,因为减法有借位,很耗时间和指令! 所以,计算CRC也是除法,但是用XOR来代替减法。

2.CRC除法:

120÷9=14 余 6,商、余数和算术除法不一定相同!!因为除法用的是XOR,而不是真正的减法。

CRC

的除法

    以下用二进制来模拟这个过程:


可见,除法(XOR)的目的是逐步消掉最高位的1或0!

  由于过程是XOR的,所以商是没有意义的,我们不要。我们要的是余数。

实际上,数据是1111,CRC是110。  对于除数1001,我们叫它生成多项式,即生成项,或POLY,即g(x)。 数据1111根据POLY1001,计算得到CRC110。  如果POLY不是1001,而是1011,那得到的CRC也是不同的!  所以生成项不同,得到的CRC也不同。要预先定义好POLY,发送端和接收端要用一样的POLY!

3..生成多项式

上面例子中,生成项是1001,共4位比特,最高位的1,实际上在除法的每次XOR时,都要消掉,所以这个1可不做参考,后3位001才是最重要的!001有3位,所以得到的余数也是3位,因为最后一次除法XOR时,最高位消掉了。所以CRC就是3位比特的。

CRC是3比特,表示它的宽度W=3。也就是说,原始数据后面要加上W=3比特的0进行扩展!

1001等价于多项式x^2+1

再如crc32生成多项式是:

1 0000 0100 1100 0001 0001 1101 1011 0111  (33个比特)

即g(x)= x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1

颠倒过来,就可以写成1110 1101 1011 1000 1000 0011 0010 0000 1

一般生成项简写时不写最高位的1,故生成项是0x04C11DB7,颠倒后的生成项是0xEDB88320      

CRC32的生成项是33比特,最高位是消掉的,即CRC值是32比特(4个字节),即宽度W=32,就是说,在计算前,原始数据后面要先扩展W=32个比特0,即4个0x00字节。

4.直接计算:

“直接计算法”就是直接模拟上面的除法的过程,来得到余数即CRC!  上面的例子中,除数是4位,但最高位是要一直消掉的,所以我们只需要一个3位的寄存器就好了。 

计算过程:  待测数据后扩展W=3个比特0,变成1111000; 

寄存器初始化置0; 先在寄存器中移入数据111;  

寄存器左移一位,并且右边移入下一位数据1。这样最高位1移出,由于最高位是1,故本次的商是1,要用除数1001来进行XOR,最高位肯定XOR得0,故不管它,只要用低3位001来进行XOR就可以,即001对寄存器进行XOR,寄存器中得到110,即第一次XOR后的结果(相当于是数据1111与生成项1001进行了一次XOR,并把最高位0消掉了)。 如果移出的最高位是0,则用0000来进行XOR(0 XOR 后,得到的还是原值)。  一直重复这个过程,就能得到最后余数了。

总共处理次数=商的位数=待测数据的位数-生成项位数+1+宽度W=待测数据的位数=4次。

我们假设待测数据是1101 0110 11,生成项是10011,假设有一个4 bits的寄存器,通过反复的移位和进行CRC的除法,最终该寄存器中的值就是我们所要求的余数

 


根据这个模型我们做一个简单的算法:

把register中的值置0.

   把原始的数据后添加w个0.

While (还有剩余没有处理的数据)                                                                                      Begin        把register中的值左移一位,读入一个新的数据并置于register最低位的位置。                          If (如果上一步的左移操作中的移出的一位是1)          register = register XOR Poly.       End

实际上就是模拟XOR除法的过程,即被测数据一位一位放到寄存器中来做除法。 比如生成项是10011,则生成的余数是4位XXXX,所以寄存器是4位。 待测数据是1101 0110 11,后面加上0000,即扩张4位,以容纳余数。 只要与生成项的0011做XOR就好了,最高位经过XOR肯定出0,可不用最高位。

过程如下:

待测数据先移4位即1101到寄存器中,准备开始除法。  第1次除法:寄存器中是1101,先从寄存器移出最高位1,移进下一位待测数据位0,则寄存器中是1010,由于移出的位是1,则需要与生成项的0011做XOR,得到1001,即做了第1次除法后,寄存器中是1001,这个就是余数。  第2次除法:寄存器中是1001,从寄存器移出最高位1,移进下一位待测数据位1,则寄存器中是0011,由于移出的位是1,则需要与生成项的0011做XOR,得到0000,即做了第2次除法后,寄存器中是0000,这个就是余数。  第3次除法:寄存器中是0000,从寄存器移出最高位0,移进下一位待测数据位1,则寄存器中是0001,由于移出的位是0,则需要不做XOR,直接下一步移位。也可以等同于:本次的商是0,0*生成项=0,即是0000与寄存器做XOR,得到寄存器的数不变,还是0001,即做了第3次除法后,寄存器中是0001,这个就是余数。        第4次除法:寄存器中是0001,从寄存器移出最高位0,移进下一位待测数据位0,则寄存器中是0010,由于移出的位是0,则需要不做XOR,直接下一步移位。   第5次除法:移位,不用做XOR,得到寄存器中是0101 第6次除法:移位,不用做XOR,得到寄存器中是1011 第7次除法:移位,移出的位是1,又要与生成项做XOR了  一直做下去。。。。。。直到最后,寄存器中的就是整个计算后的余数了。即CRC值。

5.程序实现

//网上的程序经修改 BYTE POLY=0x13;   //生成项,13H=10011,这样CRC是4比特 

 unsigned short data = 0x035B; //待测数据是35BH,12比特,注意,数据不是16比特 

         unsigned short regi = 0x0000; // load the register with zero bits  

        // augment the data by appending W(4) zero bits to the end of it. 

       //按CRC计算的定义,待测数据后加入4个比特0,以容纳4比特的CRC;

        //这样共有16比特待测数据,从第5比特开始做除法,就要做16-5+1=12次XOR

        data <<= 4; 

      // we do it bit after bit 

       for ( int cur_bit = 15; cur_bit >= 0; -- cur_bit )   //处理16次,前4次实际上只是加载数据

       {   // test the highest bit which will be poped later.   ///     in fact, the 5th bit from right is the hightest bit here   

                if ( ( ( regi >> 4 ) & 0x0001 ) == 0x1 )   

                                      regi = regi ^ POLY;    

                                           regi <<= 1;   // shift the register

                                                               // reading the next bit of the augmented data   

                                        unsigned short tmp = ( data >> cur_bit ) & 0x0001; //加载待测数据1比特到tmp中,tmp只有1比特  

                                       regi |= tmp;  //这1比特加载到寄存器中

      }  


if ( ( ( regi >> 4 ) & 0x0001 ) == 0x1 )  

                                  regi = regi ^ POLY;  //做最后一次XOR //这时, regi中的值就是CRC 


今天先总结到这,未完待续。。。。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值