简介
循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。
在数据传输过程中,无论传输系统的设计再怎么完美,差错总会存在,这种差错可能会导致在链路上传输的一个或者多个帧被破坏(出现比特差错,0变为1,或者1变为0),从而接受方接收到错误的数据。为尽量提高接受方收到数据的正确率,在接收方接收数据之前需要对数据进行差错检测,当且仅当检测的结果为正确时接收方才真正收下数据。检测的方式有多种,常见的有奇偶校验、因特网校验和CRC校验等。
CRC校验计算速度快,检错能力强,易于用硬件电路实现。从检错的正确率与速度、成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC 成为计算机信息通信领域最为普遍的校验方式。常见应用有以太网/USB通信,压缩解压,视频编码,图像存储,磁盘读写等。
CRC基本原理
模二运算
在对CRC算法进行具体说明前,先来看看什么是模二运算。
模二运算是一种二进制算法。与四则运算相同,模二运算也包括模二加、模二减、模二乘、模二除四种二进制运算。与四则运算不同的是模二运算不考虑进位和借位,即模二加法是不带进位的二进制加法运算,模二减法是不带借位的二进制减法运算。这样,两个二进制位相运算时,这两个位的值就能确定运算结果,不受前一次运算的影响,也不对下一次造成影响。模二运算是编码理论中多项式运算的基础,也是CRC校验技术中的核心部分。
模二加法:1+1=0,1+0=1,0+1=1,0+0=0。模二减法:1-1=0,1-0=1,0-1=0,0-0=0
模二乘法:11*11 = 101很容易看出:
模二加法和模二减法的结果是相同的,并且与异或(XOR)运算的结果是一致的。
模二乘除法与普通乘除法一样演算,唯一的区别是,模二乘法在部分积相加时按模二加,模二除法部分余数相减时按模二减。
这里重点关注模二除法,因为它与CRC算法密切相关,它有三个性质:
当最后余数的位数小于除数位数时,除法停止。
当被除数的位数小于除数位数时,则商数为0,被除数就是余数。
只要被除数的位数与除数一样多,不管其他位是什么数,皆可商1。
CRC算法
基于上述铺垫,我们现在可以对CRC算法进行具体说明:CRC 算法的基本思想是将传输的数据当做一个位数很长的数。将这个数模二除以另一个数。得到的余数作为校验数据附加到原数据后面。
实际应用时,发送方和接收方按以下方式通信:
发送方和接收方在通信前,约定好一个预设整数作为除数。
发送方在发送前根据原始数据和约定好的除数进行模二除法运算生成余数(即CRC码),然后将其附加到原始数据后面一起发送给接收方。
接收方收到后将其模二除以约定好的除数,当且仅当余数为0时接收方认为没有差错。
如果被除数比除数小,那么余数就是被除数本身,比如说只要传一个字节,那么它的CRC就是它自己,为避免这种情况,在做除法之前先将它移位,使它大于除数,左移除数的位数减1。
示例
假设要传输的原始数据为1101011011B,发送方和接收方在通信前约定好的除数为10011B。由于除数10011B是五位数(5bit),那么假设余数(即CRC码)为四位数(4bit)。因为现在余数未知,所以在进行模二除法运算前先将余数设为0000B,即待发送的数据为11010110110000B。下面开始进行模二除法运算来确定余数(即CRC码):
可见余数(即CRC码)为1110B,因此发送方实际发送的是11010110111110B。
CRC校验
上面通过笔算的方式,讲解了CRC计算的原理,下面来介绍一下如何进行校验。
按照上面CRC计算的结果,最终的数据帧:11010110111110B,前10位1101011011B是原始数据,后4位1110B 是 CRC结果。
接收端的校验有两种方式,一种是和CRC计算一样,在本地把接收到的数据和CRC分离,然后在本地对数据进行CRC运算,得到的CRC值和接收到的CRC进行比较,如果一致,说明数据接收正确,如果不一致,说明数据有错误。
另一种方法是把整个数据帧进行CRC运算,因为是数据相当于把原始数据左移然后加上余数,如果直接对整个数据帧进行CRC运算,那么余数应该为0,如果不为0说明数据出错。
CRC参数模型
CRC算法中,对于二进制数都是以二进制系数多项式去描述的。
对任意的二进制数都构造与其对应的一个二进制系数多项式。例如:10011B,其对应的二进制系数多项式为P ( x ) = x^4 + x + 1
一个完整的CRC参数模型应该包含以下信息:WIDTH,POLY,INIT,REFIN,REFOUT,XOROUT。
NAME:参数模型名称。
WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位
POLY:十六进制多项式,省略最高位1,如 x8 + x2 + x + 1,二进制为1 0000 0111,省略最高位1,转换为十六进制为0x07。
INIT:CRC初始值,和WIDTH位宽一致。
REFIN:true或false,在进行计算之前,原始数据是否翻转,如原始数据:0x34 = 0011 0100,如果REFIN为true,进行翻转之后为0010 1100 = 0x2c
REFOUT:true或false,运算完成之后,得到的CRC值是否进行翻转,如计算得到的CRC值:0x97 = 1001 0111,如果REFOUT为true,进行翻转之后为11101001 = 0xE9。
XOROUT:计算结果与此参数进行异或运算后得到最终的CRC值,和WIDTH位宽一致。
通常如果只给了一个多项式,其他的没有说明则:INIT=0x00,REFIN=false,REFOUT=false,XOROUT=0x00。
常用的21个标准CRC参数模型:
CRC理解
-
CRC是否能校正数据传输中的错误?
CRC只能检错,不能纠错。如果发现错误,可根据双方协议规定要求发送方重新发送
-
CRC是否能100%检错?
不是100%检错。只能说检错的概率比较高。原始信息中某位发生变化,则CRC值发生翻天覆地的变化。而不像其他校验,原始信息中某位发生变化时,
-
CRC校验的过程是什么?
发送方根据发送报文,计算出CRC值。将原始信息和该CRC值一起发送给接收方。接收方根据原始信息,按照同样的算法,计算CRC。如果计算的CRC值不正确的话,则表明在数据传输的过程中,原始信息(或者CRC值)发生错误。
-
CRC检验为什么要采用模2除法?
模2运算加减乘除和二进制加减乘除一样,唯一不同就是不进位,也不借位。因此硬件实现比较简单,可以用XOR异或门来搭建。