一. CRC的作用
CRC用于对传输的数据进行检错。数据传输中,由于信号干扰,设备电压等多种因素,可能导致传输期间电平发生变化,使传输的数据出错。若传输1400字节的正确率为99.9%,为了保证传输正确性,可传输1400字节两次,若两次传输的数据相同,则认为数据正确,从而使出错率从0.001减少为0.000001,这种方法虽然提高了正确率,但重复传输相同字节数会使有效带宽下降一半,带宽中传输了一半的冗余信息。因而需要一种传输少量冗余信息便能判断出传输的数据是否错误的算法。CRC便是这样的算法。
二. CRC在数据传输中的操作流程
在数据发送方计算待传输数据的CRC,并按照协议格式,将CRC码添加到数据包的对应位置。数据接收方接收到数据后,计算接收数据的CRC,并与发送方发送的CRC码比对,若CRC码不相同,即认为传输出错。
三. 计算CRC的流程(以CRC32为例)
CRC计算以模2运算为主,但实际上CRC算法还有多项配置,会改变计算过程,导致CRC计算结果不同。本文将以CRC32为例,介绍从原始数据计算得到最终结果的步骤,并对于与配置参数相关的步骤进行解释。
1. 计算的数据及算法
计算的原始数据为ASCII码'8',对应16进制0x38,对应2进制:00111000
截取在线CRC计算网页截图如下,网址:CRC(循环冗余校验)在线计算_ip33.com
其中有参数:
宽度:对应最终计算得出的CRC码的位宽,步骤3和步骤5第4小步需要使用
多项式:将其与原数据进行模2运算,对应步骤5
初始值:计算前将输入数据与初始值做异或运算,对应步骤4
结果异或值:将模2运算的结果与该值做异或运算,对应步骤6
输入数据反转:将输入数据按位反向输出,对应步骤2
输出结果反转:将结果按位反向输出,对应步骤7
计算结果: 0xFA005713
2. 输入反转,对应参数:REFIN=True
将输入数据按位(bit)反向输出
00111000 -> 00011100
3. 为输入数据添加32bit 0
00011100 -> 00011100 00000000 00000000 00000000 00000000
4. 与初始值异或:对应参数:初始值 INIT:0xffffffff
对应二进制:
11111111 11111111 11111111 11111111
源数据与初始值异或:
00011100 00000000 00000000 00000000 00000000
11111111 11111111 11111111 11111111
得到:
11100011 11111111 11111111 11111111 00000000
5. 与多项式做模2运算
CRC32标准多项式:
0x04C11DB7
对应二进制:
00000100 11000001 00011101 10110111
由于需要的CRC为32位,并且CRC的校验值为模2运算的余数,因而需要在32位多项式最高位之前再加一位1
得到:
1 00000100 11000001 00011101 10110111
下面是模2运算的步骤
(1) 进行异或运算 第一行为源数据,第二行为多项式,第三行为结果
1110001111111111111111111111111100000000
100000100110000010001110110110111
0110000110011111011100010010010010000000
(2)对结果再做模2运算,由于第一位为0,因而将多项式右移一位
0110000110011111011100010010010010000000
100000100110000010001110110110111
010000010101111001101100100100101000000
(3) 重复第2步的操作
010000010101111001101100100100101000000
100000100110000010001110110110111
00000000110111000101011111111110100000
(4) 重复第2步的操作
00000000110111000101011111111110100000
100000100110000010001110110110111
发现余数已经小于多项式,因而模2运算的结果为:
00000000110111000101011111111110100000
去掉前面的0,并取32bit长度,得到
00110111000101011111111110100000
6. 将模2运算结果与0xffffffff做异或,对应参数:结果异或值 XOROUT:FFFFFFFF
00110111000101011111111110100000
11111111111111111111111111111111
得到:
11001000111010100000000001011111
7. 将第6步的结果按bit顺序反向输出:对应参数:输出数据反转(REFOUT)= True
11111010000000000101011100010011
转换为16进制:
FA005713