CRC校验码学习笔记

一、CRC校验的作用

    CRC:循环冗余校验码,是数据通信领域中最常用的一种查错校验码,它的优点是信息字段和校验字段的长度可以任意选定。使用CRC的方法是,在数据传输前计算信息字段的CRC,将其作为校验字段附在帧尾一同传输;接收方执行类似的算法,将计算结果与校验字段比较;一致则说明数据传输的正确、完整,不一致说明传输错误。

    CRC不是纠错码,它只能用于检查错误。如果发现CRC出错,并不能找出错误的位置予以纠正,只能重发或丢弃。

二、CRC校验的原理

    计算CRC的算法是,用一个特殊的除法——模2除法——来计算余数,这个余数就是CRC。模2除法中的除数就是CRC校验的生成多项式,又叫生成项(POLY)。

    在计算机中普通除法的运算过程是:不断用被除数减去移位后的除数,够减则相应位的商就是1,不够减相应位的商就是0。

    模2除法的计算过程与普通除法类似,只是把加减运算换成了XOR(异或)运算。异或运算是一种位运算,计算过程中不用向上一位借位;在计算机内部实现起来更简单,速度更快。例如,二进制数1111000模2除以1101,过程如下:

____  ___ 1011

1101/1111000

____- 1101

____  001000

_______-1101

_______ 01010

________-1101

________ 0111

计算结果,商=1011,余数=111。但是,这里的余数111并不是1111000的CRC,而是1111的CRC。

为什么

因为CRC是与信息字段一起传输的。实际使用中,接收方在收到数据后会将信息字段和校验字段合在一起执行模2除法;余数=0表示传输正确,余数≠0表示传输错误。所以,在计算CRC时,需要在信息字段后面扩展填入足够位数的0,然后计算模2除法的余数。用这样的方法,可以保证信息字段的每一位都执行过异或运算。

在异或运算时,除数的最高位总会消掉,所以,余数的位数总是比除数少一位。因此,一般在描述作为除数的生成项时,不写最高位的1。这样生成项的位数就与CRC的位数一致,都等于计算CRC时需要填充的0的位数。在这种情况下:

  • 当生成项的位数为8位时,得到的CRC为CRC8;
  • 当生成项的位数为16位时,得到的CRC为CRC16;
  • 当生成项的位数为32位时,得到的CRC为CRC32;
  • 与此类推。

所以,上面的例子里,信息字段是1111,CRC是111,而生成项是101。

在这里,如果生成项不是101则计算得到的CRC就不是111。对于同一个信息字段不同的生成项得到的CRC也不同。所以,实际传输过程中,发送方和接收方要预先约定好同一个生成项。

按照规定,生成项的最低位也必须是1。

三、CRC的计算过程

1 直接计算法

最原始的计算方法是直接计算。信息字段一位一位输入,对每一位均算出一个余数,上一位得到的余数参与下一位的计算,不断循环执行,得到最终的余数就是CRC。

每次计算都将余数的最高位移出,并将一位数据移入余数的最低位;当移出的最高位是1时,本次商是1,需要再用除数异或余数;当移出的最高位是0时,本次商是0,无需执行异或。

其中的每一步计算,用C语言描述如下: 

char k=1&(crc >>( width -1)); crc <<=1; crc |= bit & 1; if (k) crc ^= poly;
//crc为余数; bit & 1为输入的位; poly为生成项; width为poly和crc的位数

这种算法,需要额外的空间临时存储移出的最高位,因此,通常采用的是另一种算法。

通用的直接计算法

实际使用的直接计算法无需额外的空间临时存储移出的最高位,也不用浪费步骤加载信息字段。它的逻辑框图如下:

其中的每一步计算,用C语言描述如下

crc=((bit & 1)!=(( crc >>( width -1))&1)) ? poly ^( crc <<1) : crc <<1;
//crc为余数; bit & 1为输入的位; poly为生成项; width为poly和crc的位数

注意:对于CRC8,width=8;对于CRC16,width=16;对于CRC32,width=32。

两种算法的等价性

可以简单证明如下:

char k=1&(crc >>( width -1)); crc <<=1; crc |= bit & 1; if (k) crc ^= poly;

char k=1&(crc >>( width -1));
crc <<=1;
crc |= bit & 1;
if (k) crc ^= poly;

char k=1&(crc >>( width -1));
crc <<=1;//此时crc最低位=0
crc ^= bit & 1;//0|x与0^x一致
if (k) crc ^= poly;

char k=1&(crc >>( width -1));
crc <<=1;
if (k) crc ^= poly; 
crc ^= bit & 1;//依据异或交换律交换顺序

第i+width步移出的最高位k来自第i步crc ^= bit &1;  语句计算的结果。由于异或具有交换律和结合律,可以将第i步的 crc ^= bit & 1; 语句推迟到第i+width步执行。此时,移出的最高位k的值将会将有所不同,正确值k’=(bit & 1)^k。第i+width步的if(k) crc ^= poly; 变为if (k’) crc ^= poly; 第i+width步的crc ^= bit & 1; 取消。实际执行内容变成:if((bit&1)!=k)crc^=poly;

第1到第width步时,crc移出的最高位全部来自crc初始值与输入的位无关。这width步的实际作用其实是,依照crc初始值装载信息字段的最初width位。将 crc ^= bit & 1; 语句推迟后,已经不需要从crc中取得信息字段的位,前width步的装载过程可以不用执行。

char k=1&( crc >>( width -1));
crc <<=1;
if((bit & 1)!=k) crc ^= poly;

char k=1&( crc >>( width -1));
crc =((bit & 1)!=k) ? poly ^( crc <<1) : crc <<1;//语句合并

crc=((bit & 1)!=(( crc >>( width -1))&1) ? poly ^( crc <<1) : crc <<1;

2 简单的驱动表法

一次输入一位的方法显然太慢了,如果能够一次输入几位就可以迅速提高计算速度。由于异或运算具有结合律,可以证明,这样是可行的。

计算方法如下所述:

先用输入余数的高几位作为索引查表,将输入余数与几位数据联合并与查表结果异或,得到输出余数。

这就是:驱动表法。其中的每一步计算过程,用C语言描述如下:

int k= crc >>( width -bits); // crc为余数; width为crc的位数; bits为每次输入的位数
crc <<=bits; crc ^= data; crc ^=table[ k ]; // data为每次输入的bits位数据; table为查找表

此处的查找表,就是驱动表法中的直接查找表;它可以用直接计算法生成。

驱动表法与直接计算法的等价性

可以简单证明如下:

for( int I =0; i < bits; i++){ //循环执行bits次直接计算法
char k=1&(crc >>( width -1)); crc <<=1; crc |= bit & 1; if (k) crc ^= poly;
}// bit & 1为data中每次输入的位

for( int i =0; I < bits; i++){
 char k=1&(crc >>( width -1)); crc <<=1; crc ^= bit & 1; if (k) crc ^= poly; //0|x与0^x一致
} 

int k= crc >>( width - bits);//提前计算k
crc <<= bits;//集中移位
crc ^= data;//由于异或交换律和结合律,所以可以集中添加bit,即:直接添加data
for(int i=1<<( bits -1),j=bits -1;i>0;i>>=1,j--) if(k & i) crc^=poly<<j;
//仍然在循环内与生成项异或,此时,每次异或的poly位于不同的位置

int k= crc >>( width -bits);
crc <<=bits; 
crc ^= data;
int x=0; for(int i=1<<( bits -1),j=bits -1;i>0;i>>=1,j--) if(k & i) x^=poly<<j;
crc^=x;//集中异或poly

int k= crc >>( width -bits);
crc <<=bits; 
crc ^= data;
crc ^= table[k];//用查表代替集中异或poly

3 通用的驱动表法(DIRECT TABLE ALGORITHM)

前面的算法,需要额外的空间临时存储移出的最高位,并且需要加载信息字段的步骤;因此,通常采用的是另一种驱动表法。计算方法如下所述:

预先计算输入余数为0时连续几位运算的输出结果,得到一张表,表的大小=2^位数;实际计算时,先将输入余数的高几位与几位数据异或,取计算结果作为索引查表,然后将查表值与输入余数的低位(高几位已移出)异或得到输出余数。

这种驱动表法是绝大多数CRC算法所通用的驱动表法。

其中的每一步计算过程,用C语言描述如下

crc = table[ data ^( crc >>( width - bits))]^( crc << bits );
//crc为余数; data为每次输入的bits位数据; width为crc的位数; table为查找表

此处的查找表,就是通用的驱动表法中的直接查找表;它可以用直接计算法生成。其中,第i表项可以由第i/2表项递推取得,第0表项为0,第1表项为生成项(POLY)。

需要指出的是:通用的驱动表法与简单的驱动表法,采用的直接查找表是相同的。

直接查找表的生成过程用C语言描述如下

if( bits >0) table[0]=0;
for( int i =1; i < 1<< bits; i++){
 table[ i ]= table[ i /2]<<1;
 if ( i & 1!= table[ i /2]>>( width -1)) table[ i ]^= poly; //递推计算
}// poly为生成项; width为poly的位数; bits为每次输入的数据位数; table为直接查找表

注意:对于CRC8,width=8;对于CRC16,width=16;对于CRC32,width=32。

通用的驱动表法与通用的直接计算法的等价性

可以简单证明如下:

for(int i=0;i<bits;i++){ //循环执行bits次通用的直接计算法
crc=((bit & 1)!=(( crc >>( width -1))&1)) ? poly ^( crc <<1) : crc <<1; 
}// bit & 1为data中每个循环步骤输入的位

for(int i=0;i<bits;i++){
char k =1&( crc >>( width -1)); crc <<=1; if(( bit & 1)!= k ) crc ^= poly;
}//k为每个循环步骤移出的crc最高位

int k= crc >>( width -bits);//提前计算k
crc <<= bits;//集中移位
for(int i =1<<( bits -1), j = bits -1; i >0; i >>=1, j--){
 if( data & i != k & i ) crc ^= poly <<j;
}//仍然在循环内与生成项异或

int k= crc >>( width -bits);
crc <<= bits;
int x=0; for( int i =1<<( bits -1), j = bits -1; i >0; i >>=1, j--) if( data & i != k & i ) x ^=poly <<j;
crc ^= x;//集中异或poly

int k= crc >>( width -bits);
crc <<= bits;
int x= table[ data ^ k ]; crc ^= x; //用查表代替集中异或poly

crc = table[ data ^( crc >>( width - bits))]^( crc << bits );

四、低位在前与高位在前

计算机系统按照位排列方式有:低位在前、高位在前,两种类型。
传输数据时,发送方会将字节码转换为位串的形式发送到通讯信道中;接收方也是以位串的形式收到的数据。如下图所示:

同一个字节码在不同的系统中,转换为位串的方法决于大小端的定义。在没有明确规定的情况下:发送方依据自己的大小端定义将字节码转换为位串,接收方依据自己的大小端定义将位串转换为字节码。当两端的大小端定义不同时,即使通讯信道正确无误,同一串字节码经过通讯信道传输后也将发生改变。因此,为了保证传输正确,通常的通讯协议都会明确规定通讯信道的大小端定义。
当跨越不同大小端的计算机系统传输数据时,收发双方中与通讯协议的大小端定义不一致的一方,在计算CRC校验时也需要适当颠倒输入数据和计算结果的位排序。在计算CRC校验前颠倒信息字段的高低位,并在输出结果时再次颠倒高低位,就可以得到所需的CRC校验值。例如:
当生成项=1021、信息字段=1234时,CRC=13C6。当通讯协议规定的大小端定义是低位在前时:发送的字节码是1234C613;当使用高位在前系统接收数据时,接收到的数据变为482C63C8。此时,CRC由于接收到的信息字段与CRC校验值均已发生变化,CRC校验失败。为了正常的进行CRC校验,需要将482C63C8颠倒高低位变为1234C613,计算得到CRC校验值=13C6,将其颠倒高低位得到63C8,与接收到的校验位一致,CRC校验成功。
但是,这样的计算方法,需要每次计算前后都颠倒高低位。有时为了效率的考虑,需要直接计算颠倒顺序的CRC校验值。下图左侧为通用的驱动表法的计算过程,下图右侧为对应的逆序算法。

 在通用的驱动表法中,信息字段的每一字节与余数的高位执行异或,余数其余位经过位移后与查找表中找到的表项执行异或运算,运算结果输出。当信息字段与余数都颠倒高低位时,余数的高位变成余数的低位,左移变成右移;信息字段的每一字节与余数中执行异或的位的位序刚好一致,异或运算不变;此时,异或的计算结果也是颠倒高低位的,因此,查表时应该用高低位颠倒后的索引查找,并且查找到的表项值也应颠倒高低位,以便与余数位序一致。

由此得到的驱动表法就是:逆序驱动表法

如果,将正常直接查找表中各表项,移动到其索引颠倒高低位后的索引位置处,并将表项值也颠倒高低位,就得到所谓的正规查找表。使用正规查找表可以直接查表,不必颠倒索引的高低位再查表,也不必查表后颠倒表项值的高低位。于是,有了如下的计算方法:

1 使用正常的直接计算法生成直接查找表;

2 交换直接查找表中每一对:索引=I与索引=颠倒I高低位的表项;然后,将所有表项颠倒的值高低位,取得正规查找表;

3 使用逆序的驱动表法计算CRC。

上述最后一步的每一次计算过程,用C语言描述如下:

icrc =( icrc >> bits )^ table[( icrc ^ data )&((1 << bits )-1)];
//icrc为余数; data为每次输入的bits位数据; table为逆序直接查找表

正规查找表的生成算法与正常的直接查找表完全相同,只是在生成查找表后需要按照索引颠倒高低位交换表项,同时颠倒每一项的值。

显然,当bits=8时,CRC8的逆序驱动表法与正常驱动表法完全相同,但两者的直接查找表完全不同。

五、CRC的使用

实际使用CRC时,需要考虑一些参数。不仅生成项POLY会影响到CRC值,这些参数也会影响到最终的CRC值。

1 初始值

CRC是一种非常好用的查错校验码,但是当信息字段以连续的0开头时,CRC将不能分辨0的位数。当出现起始位置的0数据丢失或增多时,CRC都不能识别。

为了解决这个问题,人们在使用CRC时会在信息字段前添加一串值=1的位。这种做法,等效于在计算CRC前,给CRC缓冲区中各个字节预先填入0xff。这种在计算CRC前预先填入的值就是CRC的初始值。

2 逆序输入

计算机系统按照位排列方式有:低位在前、高位在前,两种类型。即使采用同一个生成项,同一个信息字段在低位在前系统中计算得到的CRC值与在高位在前系统中计算得到的CRC值完全不同。为了兼容大小端不同的计算机系统,实际使用CRC时,需要明确规定位排列方式;当跨越不同大小端的计算机系统传输数据时,则需要适当颠倒输入数据和计算结果的位排序。这样,在输入数据前颠倒高低位,并在输出结果时再次颠倒高低位,就可以不必使用逆序算法来计算CRC;如此的直接使用正常的CRC算法,与使用逆序算法的结果完全一致。

逆序输入是指,在计算CRC时,输入信息字段的每个字节都预先颠倒其位排序,然后再加入计算。

3 逆序输出

逆序输出是指,在取得CRC后,要先颠倒CRC值的位排序,然后输出。

4 异或输出值

某些协议在使用的CRC时需要将计算得到的CRC值与某个预先定义的值异或,然后作为校验值传输。这个用于生成实际使用校验值的预定义值,就是CRC的异或输出值。

于是,实际计算CRC的计算过程如下所示:

1将初始值赋予CRC缓冲区;

2逐个字节计算CRC;计算每个字节数据前,根据逆序输入参数颠倒该字节数据的位排序;

3计算结束后,根据逆序输出参数颠倒CRC值的位排序;

4将CRC值与异或输出值相异或,异或结果作为校验值输出。

CRC校验的算法极其简单,无论是直接计算还是驱动表法,核心计算都只需要一句C语言代码。但是,CRC校验的原理非常复杂。不了解原理,很容易记错或记反代码。

通常,计算CRC时使用的查找表的索引都是8位的,这时计算CRC的C语言语句如下:

CRC8crc = table[ data ^ crc ];
CRC16crc = table[ data ^( crc >>8)]^( crc <<8);
CRC33crc = table[ data ^( crc >>24)]^( crc <<8);
CRC64crc = table[ data ^( crc >>56)]^( crc <<8);

相对的逆序算法如下:

crc = table[byte( data ^ crc )]^( crc >>8);

值得注意的是逆序算法中无论CRC8、CRC16还是CRC32…,其C语言语句完全一样,所不同之处仅仅在于其中的查找表table和校验码crc的数据类型定义。
常用的CRC直接查找表有(注意:下表中各查找表项值均为16进制形式):

CRC8
POLY=0x31
00 31 62 53 C4 F5 A6 97 B9 88 DB EA 7D 4C 1F 2E 
43 72 21 10 87 B6 E5 D4 FA CB 98 A9 3E 0F 5C 6D 
86 B7 E4 D5 42 73 20 11 3F 0E 5D 6C FB CA 99 A8 
C5 F4 A7 96 01 30 63 52 7C 4D 1E 2F B8 89 DA EB 
3D 0C 5F 6E F9 C8 9B AA 84 B5 E6 D7 40 71 22 13 
7E 4F 1C 2D BA 8B D8 E9 C7 F6 A5 94 03 32 61 50 
BB 8A D9 E8 7F 4E 1D 2C 02 33 60 51 C6 F7 A4 95 
F8 C9 9A AB 3C 0D 5E 6F 41 70 23 12 85 B4 E7 D6 
7A 4B 18 29 BE 8F DC ED C3 F2 A1 90 07 36 65 54 
39 08 5B 6A FD CC 9F AE 80 B1 E2 D3 44 75 26 17 
FC CD 9E AF 38 09 5A 6B 45 74 27 16 81 B0 E3 D2 
BF 8E DD EC 7B 4A 19 28 06 37 64 55 C2 F3 A0 91 
47 76 25 14 83 B2 E1 D0 FE CF 9C AD 3A 0B 58 69 
04 35 66 57 C0 F1 A2 93 BD 8C DF FE 79 48 1B 2A 
C1 F0 A3 92 05 34 67 56 78 49 1A 2B BC 8D DE EF 
82 B3 E0 D1 46 77 24 15 3B 0A 59 68 FF CE 9D AC
CRC8
POLY=0x7
00 07 0e 09 1c 1b 12 15 38 3f 36 31 24 23 2a 2d 
70 77 7e 79 6c 6b 62 65 48 4f 46 41 54 53 5a 5d 
e0 e7 ee e9 fc fb f2 f5 d8 df d6 d1 c4 c3 ca cd 
90 97 9e 99 8c 8b 82 85 a8 af a6 a1 b4 b3 ba bd 
c7 c0 c9 ce db dc d5 d2 ff f8 f1 f6 e3 e4 ed ea 
b7 b0 b9 be ab ac a5 a2 8f 88 81 86 93 94 9d 9a 
27 20 29 2e 3b 3c 35 32 1f 18 11 16 03 04 0d 0a 
57 50 59 5e 4b 4c 45 42 6f 68 61 66 73 74 7d 7a 
89 8e 87 80 95 92 9b 9c b1 b6 bf b8 ad aa a3 a4 
f9 fe f7 f0 e5 e2 eb ec c1 c6 cf c8 dd da d3 d4 
69 6e 67 60 75 72 7b 7c 51 56 5f 58 4d 4a 43 44 
19 1e 17 10 05 02 0b 0c 21 26 2f 28 3d 3a 33 34 
4e 49 40 47 52 55 5c 5b 76 71 78 7f 6a 6d 64 63 
3e 39 30 37 22 25 2c 2b 06 01 08 0f 1a 1d 14 13 
ae a9 a0 a7 b2 b5 bc bb 96 91 98 9f 8a 8d 84 83 
de d9 d0 d7 c2 c5 cc cb e6 e1 e8 ef fa fd f4 f3
CRC16
POLY=0x1021
0000 1021 2042 3063 4084 50A5 60C6 70E7 8108 9129 A14A B16B C18C D1AD E1CE F1EF
1231 0210 3273 2252 52B5 4294 72F7 62D6 9339 8318 B37B A35A D3BD C39C F3FF E3DE
2462 3443 0420 1401 64E6 74C7 44A4 5485 A56A B54B 8528 9509 E5EE F5CF C5AC D58D
3653 2672 1611 0630 76D7 66F6 5695 46B4 B75B A77A 9719 8738 F7DF E7FE D79D C7BC
48C4 58E5 6886 78A7 0840 1861 2802 3823 C9CC D9ED E98E F9AF 8948 9969 A90A B92B
5AF5 4AD4 7AB7 6A96 1A71 0A50 3A33 2A12 DBFD CBDC FBBF EB9E 9B79 8B58 BB3B AB1A
6CA6 7C87 4CE4 5CC5 2C22 3C03 0C60 1C41 EDAE FD8F CDEC DDCD AD2A BD0B 8D68 9D49
7E97 6EB6 5ED5 4EF4 3E13 2E32 1E51 0E70 FF9F EFBE DFDD CFFC BF1B AF3A 9F59 8F78
9188 81A9 B1CA A1EB D10C C12D F14E E16F 1080 00A1 30C2 20E3 5004 4025 7046 6067
83B9 9398 A3FB B3DA C33D D31C E37F F35E 02B1 1290 22F3 32D2 4235 5214 6277 7256
B5EA A5CB 95A8 8589 F56E E54F D52C C50D 34E2 24C3 14A0 0481 7466 6447 5424 4405
A7DB B7FA 8799 97B8 E75F F77E C71D D73C 26D3 36F2 0691 16B0 6657 7676 4615 5634
D94C C96D F90E E92F 99C8 89E9 B98A A9AB 5844 4865 7806 6827 18C0 08E1 3882 28A3
CB7D DB5C EB3F FB1E 8BF9 9BD8 ABBB BB9A 4A75 5A54 6A37 7A16 0AF1 1AD0 2AB3 3A92
FD2E ED0F DD6C CD4D BDAA AD8B 9DE8 8DC9 7C26 6C07 5C64 4C45 3CA2 2C83 1CE0 0CC1
EF1F FF3E CF5D DF7C AF9B BFBA 8FD9 9FF8 6E17 7E36 4E55 5E74 2E93 3EB2 0ED1 1EF0
CRC16
POLY=0x8005
0000 8005 800F 000A 801B 001E 0014 8011 8033 0036 003C 8039 0028 802D 8027 0022
8063 0066 006C 8069 0078 807D 8077 0072 0050 8055 805F 005A 804B 004E 0044 8041
80C3 00C6 00CC 80C9 00D8 80DD 80D7 00D2 00F0 80F5 80FF 00FA 80EB 00EE 00E4 80E1
00A0 80A5 80AF 00AA 80BB 00BE 00B4 80B1 8093 0096 009C 8099 0088 808D 8087 0082
8183 0186 018C 8189 0198 819D 8197 0192 01B0 81B5 81BF 01BA 81AB 01AE 01A4 81A1
01E0 81E5 81EF 01EA 81FB 01FE 01F4 81F1 81D3 01D6 01DC 81D9 01C8 81CD 81C7 01C2
0140 8145 814F 014A 815B 015E 0154 8151 8173 0176 017C 8179 0168 816D 8167 0162
8123 0126 012C 8129 0138 813D 8137 0132 0110 8115 811F 011A 810B 010E 0104 8101
8303 0306 030C 8309 0318 831D 8317 0312 0330 8335 833F 033A 832B 032E 0324 8321
0360 8365 836F 036A 837B 037E 0374 8371 8353 0356 035C 8359 0348 834D 8347 0342
03C0 83C5 83CF 03CA 83DB 03DE 03D4 83D1 83F3 03F6 03FC 83F9 03E8 83ED 83E7 03E2
83A3 03A6 03AC 83A9 03B8 83BD 83B7 03B2 0390 8395 839F 039A 838B 038E 0384 8381
0280 8285 828F 028A 829B 029E 0294 8291 82B3 02B6 02BC 82B9 02A8 82AD 82A7 02A2
82E3 02E6 02EC 82E9 02F8 82FD 82F7 02F2 02D0 82D5 82DF 02DA 82CB 02CE 02C4 82C1
8243 0246 024C 8249 0258 825D 8257 0252 0270 8275 827F 027A 826B 026E 0264 8261
0220 8225 822F 022A 823B 023E 0234 8231 8213 0216 021C 8219 0208 820D 8207 0202
CRC32
POLY=0X4C11DB7
00000000 04C11DB7 09823B6E 0D4326D9 130476DC 17C56B6B 1A864DB2 1E475005
2608EDB8 22C9F00F 2F8AD6D6 2B4BCB61 350C9B64 31CD86D3 3C8EA00A 384FBDBD
4C11DB70 48D0C6C7 4593E01E 4152FDA9 5F15ADAC 5BD4B01B 569796C2 52568B75
6A1936C8 6ED82B7F 639B0DA6 675A1011 791D4014 7DDC5DA3 709F7B7A 745E66CD
9823B6E0 9CE2AB57 91A18D8E 95609039 8B27C03C 8FE6DD8B 82A5FB52 8664E6E5
BE2B5B58 BAEA46EF B7A96036 B3687D81 AD2F2D84 A9EE3033 A4AD16EA A06C0B5D
D4326D90 D0F37027 DDB056FE D9714B49 C7361B4C C3F706FB CEB42022 CA753D95
F23A8028 F6FB9D9F FBB8BB46 FF79A6F1 E13EF6F4 E5FFEB43 E8BCCD9A EC7DD02D
34867077 30476DC0 3D044B19 39C556AE 278206AB 23431B1C 2E003DC5 2AC12072
128E9DCF 164F8078 1B0CA6A1 1FCDBB16 018AEB13 054BF6A4 0808D07D 0CC9CDCA
7897AB07 7C56B6B0 71159069 75D48DDE 6B93DDDB 6F52C06C 6211E6B5 66D0FB02
5E9F46BF 5A5E5B08 571D7DD1 53DC6066 4D9B3063 495A2DD4 44190B0D 40D816BA
ACA5C697 A864DB20 A527FDF9 A1E6E04E BFA1B04B BB60ADFC B6238B25 B2E29692
8AAD2B2F 8E6C3698 832F1041 87EE0DF6 99A95DF3 9D684044 902B669D 94EA7B2A
E0B41DE7 E4750050 E9362689 EDF73B3E F3B06B3B F771768C FA325055 FEF34DE2
C6BCF05F C27DEDE8 CF3ECB31 CBFFD686 D5B88683 D1799B34 DC3ABDED D8FBA05A
690CE0EE 6DCDFD59 608EDB80 644FC637 7A089632 7EC98B85 738AAD5C 774BB0EB
4F040D56 4BC510E1 46863638 42472B8F 5C007B8A 58C1663D 558240E4 51435D53
251D3B9E 21DC2629 2C9F00F0 285E1D47 36194D42 32D850F5 3F9B762C 3B5A6B9B
0315D626 07D4CB91 0A97ED48 0E56F0FF 1011A0FA 14D0BD4D 19939B94 1D528623
F12F560E F5EE4BB9 F8AD6D60 FC6C70D7 E22B20D2 E6EA3D65 EBA91BBC EF68060B
D727BBB6 D3E6A601 DEA580D8 DA649D6F C423CD6A C0E2D0DD CDA1F604 C960EBB3
BD3E8D7E B9FF90C9 B4BCB610 B07DABA7 AE3AFBA2 AAFBE615 A7B8C0CC A379DD7B
9B3660C6 9FF77D71 92B45BA8 9675461F 8832161A 8CF30BAD 81B02D74 857130C3
5D8A9099 594B8D2E 5408ABF7 50C9B640 4E8EE645 4A4FFBF2 470CDD2B 43CDC09C
7B827D21 7F436096 7200464F 76C15BF8 68860BFD 6C47164A 61043093 65C52D24
119B4BE9 155A565E 18197087 1CD86D30 029F3D35 065E2082 0B1D065B 0FDC1BEC
3793A651 3352BBE6 3E119D3F 3AD08088 2497D08D 2056CD3A 2D15EBE3 29D4F654
C5A92679 C1683BCE CC2B1D17 C8EA00A0 D6AD50A5 D26C4D12 DF2F6BCB DBEE767C
E3A1CBC1 E760D676 EA23F0AF EEE2ED18 F0A5BD1D F464A0AA F9278673 FDE69BC4
89B8FD09 8D79E0BE 803AC667 84FBDBD0 9ABC8BD5 9E7D9662 933EB0BB 97FFAD0C
AFB010B1 AB710D06 A6322BDF A2F33668 BCB4666D B8757BDA B5365D03 B1F740B4

由于对应的CRC正规查找表可以用直接查找表转换而得,此处不再附录。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值