CRC编码规则举例

循环冗余校验码

新的学期开始了,这个学期真是累啊。课超级的多啊,这几天忙着复习计算机四级,在编码上遇到些问题,正好学习下。呵呵~~~~

下面是一些资料,很不错的,感谢作者的例子让我终于明白了,光是理论太空洞了。。。。

转自:http://hi.baidu.com/ygino/blog/item/927365d0f23cab8fa0ec9cf0.html

利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。这个规则,在差错控制理论中称为“生成多项式”。


代数学的一般性算法

在代数编码理论中,将一个码组表示为一个多项式,码组中各码元当作多项式的系数。例如 1100101 表示为
1·x6+1·x5+0·x4+0·x3+1·x2+0·x+1,即 x6+x5+x2+1。

设编码前的原始信息多项式为P(x),P(x)的最高幂次加1等于k;生成多项式为G(x),G(x)的最高幂次等于r;CRC多项式为R(x);编码后的带CRC的信息多项式为T(x)。

发送方编码方法:将P(x)乘以xr(即对应的二进制码序列左移r位),再除以G(x),所得余式即为R(x)。用公式表示为
T(x)=xrP(x)+R(x)

接收方解码方法:将T(x)除以G(x),如果余数为0,则说明传输中无错误发生,否则说明传输有误。

举例来说,设信息码为1100,生成多项式为1011,即P(x)=x3+x2,G(x)=x3+x+1,计算CRC的过程为

       xrP(x)      x3(x3+x2)      x6+x5                     x
      -------- = ---------- = -------- = (x3+x2+x) + --------
        G(x)        x3+x+1       x3+x+1                  x3+x+1

即 R(x)=x。注意到G(x)最高幂次r=3,得出CRC为010。

如果用竖式除法,计算过程为

                1110
             -------    
       1011 /1100000      (1100左移3位)
             1011
             ----
              1110
              1011
              -----
               1010
               1011
               -----
                0010
                0000
                ----
                 010

因此,T(x)=(x6+x5)+(x)=x6+x5+x, 即 1100000+010=1100010

如果传输无误,

        T(x)      x6+x5+x
       ------ = --------- = x3+x2+x,
        G(x)      x3+x+1

无余式。回头看一下上面的竖式除法,如果被除数是1100010,显然在商第三个1时,就能除尽。

上述推算过程,有助于我们理解CRC的概念。但直接编程来实现上面的算法,不仅繁琐,效率也不高。实际上在工程中不会直接这样去计算和验证CRC。

下表中列出了一些见于标准的CRC资料:

名称 生成多项式 简记式* 应用举例
CRC-4 x4+x+1   ITU G.704
CRC-12 x12+x11+x3+x+1     
CRC-16 x16+x12+x2+1 1005 IBM SDLC
CRC-ITU** x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS
CRC-32 x32+x26+x23+...+x2+x+1 04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS
CRC-32c x32+x28+x27+...+x8+x6+1 1EDC6F41 SCTP

     *   生成多项式的最高幂次项系数是固定的1,故在简记式中,将最高的1统一去掉了,如04C11DB7实际上是104C11DB7。
     ** 前称CRC-CCITT。ITU的前身是CCITT。
转自:http://wsclon.gogofly.com/attachments/month_0610/crc_explain.pdf
循环冗余校验 CRC的算法分析和程序实现 
西南交通大学计算机与通信工程学院 刘东
摘要 通信的目的是要把信息及时可靠地传送给对方,因此要求一个通信系统传输消息必须可靠
与快速,在数字通信系统中可靠与快速往往是一对矛盾.为了解决可靠性,通信系统都采用了差错
控制.本文详细介绍了循环冗余校验CRC(Cyclic Redundancy Check)的差错控制原理及其算法实
现.
关键字 通信 循环冗余校验 CRC-32 CRC-16 CRC-4
概述
在数字通信系统中可靠与快速往往是一对矛盾.若要求快速,则必然使得每个数据码元所占地
时间缩短,波形变窄,能量减少,从而在受到干扰后产生错误地可能性增加,传送信息地可靠性下
降.若是要求可靠,则使得传送消息地速率变慢.因此,如何合理地解决可靠性也速度这一对矛盾,
是正确设计一个通信系统地关键问题之一.为保证传输过程的正确性,需要对通信过程进行差错控
制.差错控制最常用的方法是自动请求重发方式(ARQ),向前纠错方式(FEC)和混合纠错(HEC).
在传输过程误码率比较低时,用FEC方式比较理想.在传输过程误码率较高时,采用FEC容易出
现"乱纠"现象.HEC方式则式ARQ和FEC的结合.在许多数字通信中,广泛采用ARQ方式,
此时的差错控制只需要检错功能.实现检错功能的差错控制方法很多,传统的有:奇偶校验,校验
和检测,重复码校验,恒比码校验,行列冗余码校验等,这些方法都是增加数据的冗余量,将校验
码和数据一起发送到接受端.接受端对接受到的数据进行相同校验,再将得到的校验码和接受到的
校验码比较,如果二者一致则认为传输正确.但这些方法都有各自的缺点,误判的概率比较高.
循环冗余校验CRC(Cyclic Redundancy Check)是由分组线性码的分支而来,其主要应用是二
元码组.编码简单且误判概率很低,在通信系统中得到了广泛的应用.下面重点介绍了CRC校验
的原理及其 算法实现.
一,循环冗余校验码(CRC)
CRC校验采用多项式编码方法.被处理的数据块可以看作是一个n阶的二进制多项式,由
01
2
2
1
1axaxaxax
n
n
n++ ++


.如一个8位二进制数10110101可以表示为:
10101101234567+++++++xxxxxxx.多项式乘除法运算过程与普通代数多项式的乘除法相
同.多项式的加减法运算以2为模,加减时不进,错位,和逻辑异或运算一致.
采用CRC校验时,发送方和接收方用同一个生成多项式g(x),并且g(x)的首位和最后一
位的系数必须为1.CRC的处理方法是:发送方以g(x)去除t(x),得到余数作为CRC校验码.
校验时,以计算的校正结果是否为0为据,判断数据帧是否出错.
CRC校验可以100%地检测出所有奇数个随机错误和长度小于等于k(k为g(x)的阶数)的
突发错误.所以CRC的生成多项式的阶数越高,那么误判的概率就越小.CCITT建议:2048 kbit/s
的PCM基群设备采用CRC-4方案,使用的CRC校验码生成多项式g(x)=14++xx.采用16
位CRC校验,可以保证在1410 bit码元中只含有一位未被检测出的错误]2[.在IBM的同步数据链
路控制规程SDLC的帧校验序列FCS中,使用CRC-16,其生成多项式g(x)=1 21516+++xxx;
而在CCITT推荐的高级数据链路控制规程HDLC的帧校验序列FCS中,使用CCITT-16,其生成多
项式g(x)=1 51516+++xxx.CRC-32的生成多项式g(x)
=1 245781011121622232632++++++++++++++xxxxxxxxxxxxxx.CRC-32出错的概
率比CRC-16低510 倍]4[.由于CRC-32的可靠性,把CRC-32用于重要数据传输十分合适,所以
在通信,计算机等领域运用十分广泛.在一些UART通信控制芯片(如MC6582,Intel8273和Z80-SIO)
内,都采用了CRC校验码进行差错控制;以太网卡芯片,MPEG解码芯片中,也采用CRC-32进
行差错控制.
二,CRC校验码的算法分析
CRC校验码的编码方法是用待发送的二进制数据t(x)除以生成多项式g(x),将最后的余数
作为CRC校验码.其实现步骤如下:
(1) 设待发送的数据块是m位的二进制多项式t(x),生成多项式为r阶的g(x).在数据块
的末尾添加r个0,数据块的长度增加到m+r位,对应的二进制多项式为)(xtxr.
(2) 用生成多项式g(x)去除)(xtxr,求得余数为阶数为r-1的二进制多项式y(x).此二进
制多项式y(x)就是t(x)经过生成多项式g(x)编码的CRC校验码.
(3) 用)(xtxr以模2的方式减去y(x),得到二进制多项式)('xtxr.)('xtxr就是包含了CRC
校验码的待发送字符串.
从CRC的编码规则可以看出,CRC编码实际上是将代发送的m位二进制多项式t(x)转换成
了可以被g(x)除尽的m+r位二进制多项式)('xtxr,所以解码时可以用接受到的数据去除g(x),
如果余数位零,则表示传输过程没有错误;如果余数不为零,则在传输过程中肯定存在错误.许多
CRC的硬件解码电路就是按这种方式进行检错的.同时)('xtxr可以看做是由t(x)和CRC校验码
的组合,所以解码时将接收到的二进制数据去掉尾部的r位数据,得到的就是原始数据.
为了更清楚的了解CRC校验码的编码过程,下面用一个简单的例子来说明CRC校验码的编码
过程.由于CRC-32,CRC-16,CCITT和CRC-4的编码过程基本一致,只有位数和生成多项式不
一样.为了叙述简单,用一个CRC-4编码的例子来说明CRC的编码过程.
设待发送的数据t(x)为12位的二进制数据100100011100;CRC-4的生成多项式为g(x)
=14++xx,阶数r为4,即10011.首先在t(x)的末尾添加4个0构成)(4xtx,数据块就成了
1001000111000000.然后用g(x)去除)(4xtx,不用管商是多少,只需要求得余数y(x).下表为
给出了除法过程.
从上面表中可以看出,CRC编码实际上是一个循环移位的模2运算.对CRC-4,我们假设有
除数次数
被除数/ g(x)/结果
余数
1 001000111000000
1 0011
0
0 000100111000000
100111000000
1 00111000000
1 0011
1
0 00001000000
1000000
1 000000
1 0011
2
0 001100
1100
一个5 bits的寄存器,通过反复的移位和进行CRC的除法,那么最终该寄存器中的值去掉最高一位
就是我们所要求的余数.所以可以将上述步骤用下面的流程描述:
//reg是一个5 bits的寄存器
把reg中的值置0.
把原始的数据后添加r个0.
While (数据未处理完)
Begin
If (reg首位是1)
reg = reg XOR 0011.
把reg中的值左移一位,读入一个新的数据并置于register的0 bit的位置.
End
reg的后四位就是我们所要求的余数.
这种算法简单,容易实现,对任意长度生成多项式的G(x)都适用.在发送的数据不长的情
况下可以使用.但是如果发送的数据块很长的话,这种方法就不太适合了.它一次只能处理一位数
据,效率太低.为了提高处理效率,可以一次处理4位,8位,16位,32位.由于处理器的结构基
本上都支持8位数据的处理,所以一次处理8位比较合适.
为了对优化后的算法有一种直观的了解,先将上面的算法换个角度理解一下.在上面例子中,
可以将编码过程看作如下过程:
由于最后只需要余数,所以我们只看后四位.构造一个四位的寄存器reg,初值为0,数据依
次移入reg0(reg的0位),同时reg3的数据移出reg.有上面的算法可以知道,只有当移出的数据
为1时,reg才和g(x)进行XOR运算;移出的数据为0时,reg不与g(x)进行XOR运算,相
当与和0000进行XOR运算.就是说,reg和什么样的数据进行XOR移出的数据决定.由于只有一
个bit,所以有12种选择.上述算法可以描述如下,
//reg是一个4 bits的寄存器
初始化t[]={0011,0000}
把reg中的值置0.
把原始的数据后添加r个0.
While (数据未处理完)
Begin
把reg中的值左移一位,读入一个新的数据并置于register的0 bit的位置.
reg = reg XOR t[移出的位]
End
上面算法是以bit为单位进行处理的,可以将上述算法扩展到8位,即以Byte为单位进行处理,
即CRC-32.构造一个四个Byte的寄存器reg,初值为0x00000000,数据依次移入reg0(reg的0
字节,以下类似),同时reg3的数据移出reg.用上面的算法类推可知,移出的数据字节决定reg和
什么样的数据进行XOR.由于有8个bit,所以有82种选择.上述算法可以描述如下:
//reg是一个4 Byte的寄存器
初始化t[]={…}//共有82=256项
把reg中的值置0.
把原始的数据后添加r/8个0字节.
While (数据未处理完)
Begin
把reg中的值左移一个字节,读入一个新的字节并置于reg的第0个byte的位置.
reg = reg XOR t[移出的字节]
End
算法的依据和多项式除法性质有关.如果一个m位的多项式t(x)除以一个r阶的生成多项式
g(x),0
1
1
2
2
2
2
1
1)(axaxaxaxaxtm
m
m
m+++ ++=


,将每一位k
kxa(0= 24) & 0xFF; //要移出的字节的值
oldcrc=crc_32_tab[t]; //根据移出的字节的值查表
c=DataBuf[charcnt]; //新移进来的字节值
oldcrc32= (oldcrc32 << 8) | c; //将新移进来的字节值添在寄存器末字节中
oldcrc32=oldcrc32^oldcrc; //将寄存器与查出的值进行xor运算
charcnt++;
}
crc32=oldcrc32;
return crc32;
}
参数表可以先在PC机上算出来,也可在程序初始化时完成.下面是用于计算参数表的c语言
子程序,在Visual C++ 6.0下编译通过.
#include
unsigned long int crc32_table[256];
unsigned long int ulPolynomial = 0x04c11db7;
unsigned long int Reflect(unsigned long int ref, char ch)
{ unsigned long int value(0);
// 交换bit0和bit7,bit1和bit6,类推
for(int i = 1; i < (ch + 1); i++)
{ if(ref & 1)
value |= 1 <>= 1; }
return value;
}
init_crc32_table()
{ unsigned long int crc,temp;
// 256个值
for(int i = 0; i <= 0xFF; i++)
{ temp=Reflect(i, 8);
crc32_table[i]= temp<< 24;
for (int j = 0; j < 8; j++){
unsigned long int t1,t2;
unsigned long int flag=crc32_table[i]&0x80000000;
t1=(crc32_table[i] << 1);
if(flag==0)
t2=0;
else
t2=ulPolynomial;
crc32_table[i] =t1^t2 ; }
crc=crc32_table[i];
crc32_table[i] = Reflect(crc32_table[i], 32);
}
}
结束语
CRC校验由于实现简单,检错能力强,被广泛使用在各种数据校验应用中.占用系统资源
少,用软硬件均能实现,是进行数据传输差错检测地一种很好的手段.
参考文献
[1] 王新梅 肖国镇. 纠错码-原理与方法.西安:西安电子科技大学出版社,2001
[2] 罗伟雄 韩力 原东昌 丁志杰 通信原理与电路. 北京:北京理工大学出版社,1999
[3] 王仲文 ARQ编码通信.北京:机械工业出版社,1991
[4] Ross Williams, A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS.
Document url: http://www.repairfaq.org/filipg/ ,1993

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值