由于线路噪音,数据在通信线路上串行传送时,错误位数通常为几位或多位。例如,电话线路噪音就将引起多位错误,在这种情况下,奇偶校验和汉明校验的作用就不大了。此时我们采用循环冗余检查,即CRC(Cyclic Redundancy Check)。
CRC校验具有三个优点:侦错能力强、系统消耗小、使用简单。CRC校验保护的单位是数据块。数据块的大小根据实际情况而定。每一个数据块均被看作是一个二进制多项式,即所有系数均为二进制(即1或0)的多项式。例如,[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=21 alt="" src="http://pic.aIhUaU.com/201602/15/103735465.jpg" width=68 border=0> 就是一个二进制多项式。二进制多项式的一个最大特点是:所有的二进制的位流(比特流)均可用一个二进制多项式表示。例如,101101即可表示为:[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=27 alt="" src="http://pic.aIhUaU.com/201602/15/103751783.jpg" width=93 border=0> 。
因为每个数据块被看作一个二进制流,而每个二进制流又能够以一个二进制多项式表示,这就意味着所有的数据块均可用一个二进制多项式表示。如果我们将这个二进制多项式除以一个事先选定的二进制多项式(也称为校验多项式),则可以获得一个余数。如果我们能够使得每个数据块除以给定的多项式后余数都一样(通常为0),则可以进行数据校验。
当然,自然的数据块不可能在除以给定的多项式后余数都为0。因此,我们可以通过在数据块后面增加一个编码,使得增加编码后的新数据块在除以给定的多项式后的余数为0。这个增加的编码就是CRC码,即循环冗余码。这个码之所以称为循环冗余码是因为其产生方式是循环产生的。我们下面就来介绍CRC码的生成。
为了方便说明CRC校验原理,我们引入如下符号:
M:为要保护的数据块,假定为k位。
C:为计算出来的CRC码,假定程度为n位。
P:为某个事先决定的多项式,假定为n+1位。
T:M+C
CRC校验的核心思想是使得增加CRC码后的数据块(M+C),即T,在除以一个事先约定的多项式P后,余数为0。即:T mod P = 0。
首先我们注意到,在增加CRC码C后,新的数据块可表示为:[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=26 alt="" src="http://pic.aIhUaU.com/201602/15/103856314.jpg" width=119 border=0> 。这是因为增加C码后M相当于往左移位n位。
为了确保增加CRC码后的数据块恰好被多项式P整除,我们按如下方式获得CRC码:
假定我们先以M*x^n 除以P, 我们将获得一个商数Q和余数R,即::[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=27 alt="" src="http://pic.aIhUaU.com/201602/15/103916483.jpg" width=163 border=0> 。而这个余数就是我们需要的CRC码。
如果我们将这个余数增加到数据块M上,有:[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=22 alt="" src="http://pic.aIhUaU.com/201602/15/103937399.jpg" width=124 border=0> 。将这个T除以P,我们有:
[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=29 alt="" src="http://pic.aIhUaU.com/201602/15/103958257.jpg" width=580 border=0>
根据二进制的加法原理,一个数加到自己身上,其结果为0(模数2加法)。即上述等式中的余数将为0,因此T/P = Q。这证明R确实是我们要算的CRC码。
例如:假定要保护的数据块M=1010001101,选定的二进制多项式是[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=31 alt="" src="http://pic.aIhUaU.com/201602/15/104027280.jpg" width=206 border=0> (6位),则CRC码计算如下:
余数R=M mod P=1010001101 mod 110101=1110
CRC码C=01110(在余数前面添0直到长度为n时止)
使用CRC码的方式如下:
发送端或数据提供端:
1.读取原始数据块(要保护的数据块)
2.将该数据块左移n位后除以P
3.将余数作为CRC码附在数据块最后面
4.传送增加CRC码的数据块。
数据接收方或使用方做如下校验:
1.接收到数据块
2.将数据块除以P
3.余数为0则接收,否则认为数据块错误。
CRC校验可以在软件或者硬件上实现。由硬件实现时,CRC 通常为串行生成(即一位一位的生成),其串行生成器通常由XOR逻辑门组成,而XOR门的数量与位置由某一选定的多项式决定。具体的说,针对有n+1项的多项式,CRC实现电路包括如下部件:
1.一个长度为n位的移位寄存器(n=多项式长度-1,即CRC码的长度)
2.该实现电路可包含最多n+1个异或门(XOR)
3.在(选定的)多项式里面出现的项,在电路里相应位置即有一个异或门。
例如,针对多项式[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=26 alt="" src="http://pic.aIhUaU.com/201602/15/104054116.jpg" width=131 border=0> (即110101),我们的CRC生成器如图3-5所示:
[TR]
[TD][I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=256 alt="" src="http://pic.aIhUaU.com/201602/15/103519246.jpg" width=651 border=0>[/TD][/TR]
[TR]
[TD](点击查看大图)图3-5基于多项式x5+x4+x2+x的CRC生成与校验电路[/TD][/TR]
例如,如果要保护的数据M=1010001101,则上述硬件电路将产生CRC码01110。
图3-6为基于多项式[I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=23 alt="" src="http://pic.aIhUaU.com/201602/15/104111130.jpg" width=92 border=0> 的CRC生成器。
[TR]
[TD][I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=185 alt="" src="http://pic.aIhUaU.com/201602/15/103605261.jpg" width=687 border=0>[/TD][/TR]图3-7描述使用CRC代码时的数据传输模式。
[TR]
[TD][I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=295 alt="" src="http://pic.aIhUaU.com/201602/15/103628235.jpg" width=544 border=0>[/TD][/TR]
[TR]
[TD](点击查看大图)图3-7使用CRC代码的数据传输模式[/TD][/TR]
由硬件实现的CRC码生成器不光可以用来生成CRC码,也可以用来校验CRC码。只不过在生成和校验时的输入不同而已。当产生CRC码时,该电路的输入的是原始数据(即要保护的数据),然后n个0(表示左移n位)。异或和移位操作结束后,寄存器里剩下的即是CRC码。当检查CRC码时,该电路的输入是接收到的数据帧(即原始数据加CRC码)。在经过这些异或和移位操作后,寄存器里面的值应该为0。如果不为0,则表示数据有错。
CRC算法也可以由软件实现。最简单的办法就是将上述硬件实现用程序代码予以实现:即将移位寄存器用一个变量表示,而异或门则用xor操作表示。这种办法非常简单且内存资源占用少。但此种方法的性能不佳。当CRC生成过程所用时间是一个重要的考虑因素时,则必须使用快速软件算法。这些快速算法处理的单位是字节(而不是比特位)。但这些算法也有缺点,主要是需要在内存保持一系列的表格,因此内存消耗大。
CRC 只能检查错误,不能纠正错误,但CRC 能够检查多位错误(3位以上)。很显然,CRC校验的好坏取决于选定的多项式。因此,如何选定这个多项式是有讲究的。到底如何选定这个校验多项式不在本书讨论范围。表格3-1给出常用的几个校验多项式:
表格3-1常用校验多项式
[TR]
[TD][I]498)this.width=498;' onmousewheel = 'javascript:return big(this)' height=116 alt="" src="http://pic.aIhUaU.com/201602/15/103656966.jpg" width=458 border=0>[/TD][/TR]当然,编码技术还有很多种,用于如光盘数据纠错的Soloman码;用于卫星数据传送的Coset编码;用于无线通讯的Turbo编码方式和时空trellis编码;用于星载遥控装置容错的BCH纠错码、删信码等。有兴趣的读者可自行查阅相关参考资料。