2018/02/08 再次更新
———————————————————————————————————————————
本次更新的目的是主要进行一次再排版,顺畅文章的思路。
同时鉴于一些网友私信问我的一些问题进行解答。我自己最近再次琢磨了下CRC也发现了一些问题,会在相应章节进行细节补充,也进行勘误。
——————————————————————————————————————————
以下内容是参考网上一些大神的博客整理写出的总结,加上代码参考,仅供参考。如有疑问,欢迎大家提出一起学习交流。
引言:
在数据传送过程中,为了能够进行错误检测,往往在数据后追加一些校验码。在讲CRC校验的由来前,先简单说一下奇偶校 验及校验和。
奇偶校验:
在数据传输过程,尤其是传送串口数据时,有奇校验和偶校检,考虑如下字节:
00101100
若采用奇校验位则最后会补一位0,若采用偶校验则会补一位1。
判断补0或补1其实很简单,奇校验凑奇数个‘1’,偶校验凑偶数个’1‘。
这个校验应该算是所有数据校验中最简单的了,然而它也有不足之处:如果数据传输过程只有奇数个码位变化,那么不管 变化在哪我们判断数据传输错误是对的,但是一旦有2位发生了变化,我们就无法检测到错误,该方法的校错率是50%。
校验和(累加求模):
由于奇偶校验并的校错率达50%,那么自然有了其它校验方法,常见的则是校验和,校验和顾明思义就是对传送的数据进 行相加,并将校验的结果添加到数据末端,以传送如下8位数据如下:
0x01,0xFF,0x02,0xC0
那么在传输数据时,就会往数据里面再加上一个校验字节(如果字数据加一个word,以此类推),上述的校验和结果是 0xC2,这样0xC2就会被添加到数据末端。 那么校验和的校验出错的概率是多少呢,以传2个2位数为例
上面的结果表明,假设我传的数据 是 00 ,00那么校验和应该是00,但是实际上还有3种组合相加校验和也是00,怎么确定 原来的数据就是00,00呢,所以有3/16的概率会校验出错的,近似取1/4。(当然错一位的概率要比错两位的概率高,这点我 们不深究)
如果是N个2位数据呢,因为所有的数据结果都是均匀分配的,2位有4种结果,那么就有1/4的概率检测错误数据传输。
同理,对于字节校验有1/256的概率无法检测错误数据传输,数据的位宽越大,校验出错概率越低。
因此,CRC还算不上是好的算法, 好的算法要求数据的数据能散列的分布在检测码,CRC便应运而生。
CRC的背景理论
CRC(Cyclic Redundancy Check,循环冗余检验)是基于数据计算一组效验码,用于核对数据传输过程中是否被更改或传输错误。
CRC校验的原理是将数据追加结尾的nbits的0当作一个很大阶的多项式, 用它去除于另一个双方约定的多项式,得到的余 数,作为校验码,其中w为约定多项式的最大阶数, 最后传输原始数据追加检测码,其中任何一位发生变化,都导致最后得到 的结果差别很大。CRC因为容易简单实现以及容错性强, 而被广泛使用。
算法原理
关于算法原理, 循环冗余检验 (CRC) 算法原理 - Cheney Shue - 博客园 作了比较详细的介绍,诸位可以
参考上述链接,然后跳到代码实现部分,以下是从上述算法原理的摘抄总结。
假设数据传输过程中需要发送15位的二进制信息g=101001110100001,这串二进制码可表示为代数多项式g(x) = x^14 + x^12 + x^9 + x^8 + x^7 + x^5 + 1,其中g中第k位的值,对应g(x)中x^k的系数。将g(x)乘以x^m,既将g后加m个0, 然后除以m阶多项式h(x),得到的(m-1)阶余项r(x)对应的二进制码r就是CRC编码。
h(x)可以自由选择或者使用国际通行标准,一般按照h(x)的阶数m,将CRC算法称为CRC-m,比如CRC-32、CRC-64等。国际通行标准可以参看http://en.wikipedia.org/wiki/Cyclic_redundancy_check
定义g(x) 与 h(x)的除运算是m 次循环移位异或运算,如上例g(x) 与 h(x)的除运算如下
经过迭代运算后,最终得到的r是10001100,这就是CRC效验码。
CRC直接移位算法:
通过示例,可以发现一些规律,依据这些规律调整算法:
1. 每次迭代,根据gk的首位决定b,b是与gk进行运算的二进制码。若gk的首位是1,则b=h;若gk的首位是0,则b=0, 或者跳过此次迭代,上面的例子中就是碰到0后直接跳到后面的非零位。
2.