CRC校验

来源:互联网 发布:java swing表单实例 编辑:程序博客网 时间:2024/05/21 19:42

CRC校验,即循环冗余校验,作为在数据通信领域常用的一种差错校验方式,CRC校验比奇偶校验检错能力更强,因此应用也更加广泛。一般来说,硬件部分在接收到帧的时候已经帮我们完成CRC计算,如果发现数据有误,则丢弃该帧,且不对该帧进行回复。发送方在收不到回复帧的情况下会对该帧进行重传。虽然CRC校验可以靠硬件完成,然而在嵌入式开发中,由于低成本的微控制器系统很难通过硬件的支持实现CRC校验,因此很多时候需要我们用CRC完成对各种数据的校验,因此掌握CRC校验依然重要。

CRC校验基本原理

假设我们传送的数据有K位二进制码,首先选定一个R位的二进制除数,然后将K位二进制码左移(R-1)位。左移完成后,用(K+R-1)位的新二进制码数据去除R位的二进制除数,并得到一个(R-1)位的余数。值得注意的是,如果这个余数不足(R-1)位,则在高位用0填充。然后,将该余数附加在原来的K位二进制码数据的后面,封装之后进行传送。当接收方接收后帧(K+R-1)后,用该帧去除以前面的R位二进制除数,如果得到的余数为0,则表示传输过程中没有出错。

上面讲的便是CRC校验的基本原理,字面上可能不太好理解,下面结合例子则会比较好懂。不过在讲例子之前,我们应该先搞清楚两点。

(1)二进制除数的选择

在CRC校验中,由于除数通常以多项式表示,因此也被称为生成多项式。生成多项式可随机选取,也可使用国际上通行的标准,但有一点必须遵守的是,除数的最高位和最低位必须为1,如10001001。由于多项式如果选的不好可能会影响校验的结果,因此可以选取的下面的几个较通用的多项式作为除数:

CRC8=X8+X5+X4+X0

CRC16=X16+X15+X2+X0

CRC12=X12+X11+X3+X2+X0

CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0

值得注意的是,CRC8中的8,CRC16的16以及CRC32中的32称为位宽。而除数的位数并不等于位宽,而是等于位宽+1。因此,上面多个生成多项式转化为二进制除数的时候的位数实际为9,17,33,对应的二进制比特串分别为:100110000,11000000000000100,100000100110000010001110110110110。

(2)模2运算

在CRC中用到的除法与普通的除法不一样,因为当它在做加减法运算时既不进位,也不借位,相当于二进制中的异或运算。

加法不进位,即1+1=0,1+0=1,0+1=1,0+0=0

减法不借位,即1-1=0,1-0=1,0-1=1,0-0=0

举个例子,如下图所示:


可以看到,采用模2除法之后元素不用考虑进位,也不用考虑借位,变得简单多了。

CRC校验例子

上面说基本原理用文字描述可能还有点难懂,接下来结合例子说明:

假设我们传送的K位数据的二进制码为110101101,除数选为11001,即生成多项式G(x)= x5+x4+x0

首先将数据左移(5-1)位,可得1101011010000,然后去除11001,过程如下图:


余数1010便是CRC冗余码了,把CRC冗余码1010附加在110101101后面传送,即1101011011010。然后在接收端同样使用模2除法,用1101011011010除以“约定”的除数11001,如果余数为0,则表明数据在传送过程中并没有发生错误。否则则表示出错。

以上内容便是CRC校验码的一个简单过程,当然在传送帧时使用的CRC校验还要考虑更多的东西,比如帧一般有几百个字节,如果按位计算CRC,虽然过程比较简单,然而却会占用很多的CPU时间,这在某些需要高速通讯的场合时是不能容忍的。因此,此时便可以考虑按字节校验,可以更高效的利用CPU。另外还有一点需要注意,就是X86采用的是小端字节序,而网络传输采用的是大端字节序,因此在校验之前别忘了先进行字节序的转换。

关于CRC校验就写到这里了,至于代码就以后有时间再写了贴出来。