CRC校验原理

CRC校验三个关键流程:
1、选取一个除数。
2、需要校验的数据为被除数。
3、模2除法的余数为校验结果。

一、模二除法

定义:二进制数据的异或运算。
备注:异或运算“相同为零,不同为1”。

二、选择除数(CRC生成多项式)

二进制可表示成多项式的形式,比如二进制1001表示为: x3+x0;0011表示为:x1+x0。
生成多项式的选取是有一定标准的,该多项式可以是任何数学多项式(没有任何系数),但是它的最高指数不能超过CRC的位数。
比如我们要生成一个8位CRC(CRC-8),那么多项式的最高指数也必须是8,比如:x8+x2+x+1。
选择除数,需要考虑两个方面:随机错误检测精度、突发错误检测精度。

(1)随机错误检测精度

随机错误是指在数据中随机出现的错误。例如,在传输数据时,单个比特被翻转,或者在传输过程中丢失几个比特。根据我们使用的CRC的位大小,我们可以检测到大多数这些随机错误。然而,对于CRC-n来说,这些错误的1/2^n。
CRC 不可检测错误 百分比
CRC-8 1/2^8 0.39
CRC-16 1/2^16 0.0015
CRC-32 1/2^32 0.00000002
CRC-64 1/2^64 5.4*10^(-20)

(2)突发错误检测精度

数据传输中的错误通常不是随机的,而是连续的出现几个位的错误,这种错误称为突发错误,它是数据通信中最常见的错误。CRC-n可以检测最大长度为n位的单突发错误。

CRC 不可检测错误
CRC-8 至少出现一个连续的错误突发,但这个长度≤8位
CRC-16 至少出现一个连续的错误突发,但这个长度≤16位
CRC-32 至少出现一个连续的错误突发,但这个长度≤32位
CRC-64 至少出现一个连续的错误突发,但这个长度≤64位

(3)标准的CRC生成多项式

CRC校验原理_第1张图片

三、被除数处理

1、需要在被除数后加n-1个比特位0

具体加几个0是根据除数的位数决定的,比如除数为CRC-8,那么A后面加7个0;如果除数为CRC-16,则A后面加15个0。

2、模2除法具有下列三个性质:

当最后余数得位数小于除数位数时,除法停止;
当被除数得位数小于除数位数时,则商数为0,被除数就是余数;
只要被除数或部分余数得位数与除数一样多,且最高位为1,不管其他位是什么数,皆可商1;

3、实例

给定一组数据A:10110011(二进制),选取除数B:11001。
首先需要在被除数A后加4个比特位0(具体加几个0是根据除数B的位数决定的,比如这里B是5位,那么A后面加4个0;如果B选6位,则A后面加5个0,总之加的0的个数比除数B的个数少1位。后面还会提到怎么添加)。
进行模2除法运算。注意每次都是模2运算,即异或。
最后得到余数C就是CRC校验值。注意余数位数必须比除数少1位,如果不够前面加0补齐。运算如下图所示
CRC校验原理_第2张图片

四、实际的CRC计算过程

1、四个概念:余数初始值、结果异或值、输入数据反转、输出数据反转。

余数初始值:即在计算开始前,先给变量CRC赋的初值。
输入数据反转:即在计算开始前,将需要校验的数据反转,如数据位1011,反转后为1101。
结果异或值:即在计算结束后,得到的变量CRC与这个值进行异或操作,就得到了最终的校验值。
输出数据反转:即在计算结束后,与结果异或值异或之前,计算值反转,如计算结果为1011,反转后为1101。
2、CRC参数模型
CRC校验原理_第3张图片

2、CRC-16/IBM校验实例

预置1个16位的变量CRC,存放校验值,首先根据表3-1赋初值0x0000;
将第1个字节按照表3-1看是否需要反转,若需要,则按反转,若不需要,直接进入第3步。这里需要反转;
把第1个字节按照步骤2处理后,与16位的变量CRC的高8位相异或,把结果放于变量CRC,低8位数据不变;
把变量CRC的内容左移1位(朝高位)用0填补最低位,并检查左移后的移出位;
如果移出位为0:重复第4步(再次左移一位);如果移出位为1,变量CRC与多项式8005(1000 0000 0000 0101)进行异或;
重复步骤4和5,直到左移8次,这样整个8位数据全部进行了处理;
重复步骤2到步骤6,进行通讯信息帧下一个字节的处理;
将该通讯信息帧所有字节按上述步骤计算完成后,将得到的16位变量CRC按照表3-1看是否需要反转,这里需要反转;
最后,与结果异或值异或,得到的变量CRC即为CRC校验值;

/*****************************************************************************
*function name:crc16
*function: CRC校验,校验值为16位
*input:addr-数据首地址;num-数据长度(字节);type-CRC16的算法类型
*output:16位校验值
******************************************************************************/
u16 crc16(u8 *addr, int num,CRC_16 type)  
{  
    u8 data;
    u16 crc = type.InitValue;					//初始值
    int i;  
    for (; num > 0; num--)               
    {  
        data = *addr++;
        if(type.InputReverse == TRUE)
            data = reverse8(data);				//字节反转
        crc = crc ^ (data<<8) ;					//与crc初始值高8位异或 
        for (i = 0; i < 8; i++)					//循环8位 
        {  
            if (crc & 0x8000)					//左移移出的位为1,左移后与多项式异或
                crc = (crc << 1) ^ type.poly;    
            else		                        //否则直接左移
                crc <<= 1;                  
        }
    }
    if(type.OutputReverse == TRUE)              //满足条件,反转
        crc = reverse16(crc);
    crc = crc^type.xor;	                        //最后返与结果异或值异或
    return(crc);                                //返回最终校验值
}

你可能感兴趣的:(算法,CRC校验原理)