CCITT CRC-16计算原理与实现_第1页
CCITT CRC-16计算原理与实现_第2页
CCITT CRC-16计算原理与实现_第3页
CCITT CRC-16计算原理与实现_第4页
CCITT CRC-16计算原理与实现_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、CCITT CRC-16计算原理与实现CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除数据通信外,CRC在其它很多领域也是大有用武之地的。例如我们读软盘上的文件,以及解压一个ZIP文件时,偶尔会碰到“Bad CRC”错误,由此它在数据存储方面的应用可略见一斑。 差错控制理论是在代数理论基础上建立起来的。这里我们着眼于介绍CRC的算法与实现,对原理只能捎带说明一下。若需要进一步了解线性码、分组码、循环码、纠错编码等方面的原理,可以阅读有关资料。 利用C

2、RC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,然后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。这个规则,在差错控制理论中称为“生成多项式”。 1 代数学的一般性算法 在代数编码理论中,将一个码组表示为一个多项式,码组中各码元当作多项式的系数。例如 1100101 表示为 1·x6+1·x5+0·x4+0·x3+1·x2+0·x+1,即 x6+x5+x2+1。 设

3、编码前的原始信息多项式为P(x),P(x)的最高幂次加1等于k;生成多项式为G(x),G(x)的最高幂次等于r;CRC多项式为R(x);编码后的带CRC的信息多项式为T(x)。 发送方编码方法:将P(x)乘以xr(即对应的二进制码序列左移r位),再除以G(x),所得余式即为R(x)。用公式表示为 T(x)=xrP(x)+R(x) 接收方解码方法:将T(x)除以G(x),如果余数为0,则说明传输中无错误发生,否则说明传输有误。 举例来说,设信息码为1100,生成多项式为1011,即P(x)=x3+x2,G(x)=x3+x+1,计算CRC的过程为     &

4、#160; xrP(x)     x3(x3+x2)     x6+x5                    x     - = - = - = (x3+x2+x) + -       G(x)   

5、;    x3+x+1      x3+x+1                 x3+x+1即 R(x)=x。注意到G(x)最高幂次r=3,得出CRC为010。 如果用竖式除法,计算过程为               

6、1110            -         1011 /1100000     (1100左移3位)            1011          

7、  -             1110             1011             -          

8、0;   1010              1011              -               0010     

9、;          0000               -                010因此,T(x)=(x6+x5)+(x)=x6+x5+x, 即 1100000+010=1100010 如果传输无误, &

10、#160;      T(x)     x6+x5+x      - = - = x3+x2+x,       G(x)     x3+x+1无余式。回头看一下上面的竖式除法,如果被除数是1100010,显然在商第三个1时,就能除尽。 上述推算过程,有助于我们理解CRC的概念。但直接编程来实现上面的算法,不仅繁琐,效率也不高。实际上在工程中不会直接这样去计算

11、和验证CRC。 下表中列出了一些见于标准的CRC资料: 名称   生成多项式   简记式*   应用举例 CRC-4   x4+x+1      ITU G.704 CRC-12   x12+x11+x3+x+1       CRC-16   x16+x12+x2+1   1005   IBM SDLC CRC-ITU*   x16+x12+x5+1   1021   ISO HDLC, ITU X.25, V.34

12、/V.41/V.42, PPP-FCS CRC-32   x32+x26+x23+.+x2+x+1   04C11DB7   ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS CRC-32c   x32+x28+x27+.+x8+x6+1   1EDC6F41   SCTP     *  生成多项式的最高幂次项系数是固定的1,故在简记式中,将最高的1统一去掉了,如04C11DB7实际上是104C11DB7。    * 前

13、称CRC-CCITT。ITU的前身是CCITT。 4.CRC算法的实现 - 要用程序实现CRC算法,考虑对第2节的长除法做一下变换,依然是M = 11100110,G = 1011, 其系数r为3。                                   &

14、#160;      11001100                           -              1011 )11100110000 &

15、#160;                         1011.                          

16、;       -.                                     1010.       &

17、#160;                        1011.                  -.         &#

18、160;                        1110.                           

19、        1011.                                      -.     &#

20、160;                                   1010.               &

21、#160;                      1011.                             

22、;          -                                         &#

23、160;  100  <-校验码                                  程序可以如下实现:     1)将Mxr的前r位放入一个长度为r的寄存器;     2)如果寄

24、存器的首位为1,将寄存器左移1位(将Mxr剩下部分的MSB移入寄存器的LSB),       再与G的后r位异或,否则仅将寄存器左移1位(将Mxr剩下部分的MSB移入寄存器的LSB);     3)重复第2步,直到M全部Mxr移入寄存器;     4)寄存器中的值则为校验码。     基于以上算法,我们可以看一下上面例子的程序计算过程:(r3)       首先,111 00110000前三位进入

25、寄存器,即111        这时寄存器首位为1,执行第2步,移位成110 0110000,这时寄存器中为前三位110,将其与011(生成多项式后三位)异或,得101 0110000.         然后继续第2步,101首位为1,移位010 110000,然后010与011异或,得  001 110000 前面两个0,连续以为2次且不用计算异或,得111 0000,接着移位110 000,异或得101 000    &#

26、160;   第一位为1,移位得010 00,前三位异或得001 00        最后因为前面两个0,直接移位两次后得寄存器中的内容100,这时Mxr位的所有内容都移入寄存器,运算结束,记得检验码为100。(关键先判断首位是否为1,然后移位,然后计算)          111 00110000移位>1 110 0110000         &#

27、160;                                       011           

28、60;                                     101 0110000  ->101第一位为1,移位且计算        

29、                                         1 010 110000        

30、0;                                           011        

31、;                                            001 110000->001第一位第二位均为0,移位2次  &

32、#160;                                                 00 111

33、 0000->111第一位为1,移位且计算                                               

34、;          1 110 000                                        

35、                    011                               &

36、#160;                            101 000->101第一位为1,移位且计算                  

37、60;                                         1 010 00         

38、;                                                  

39、;    011                                               

40、                001 00->移位2次得100 用CRC16-CCITT的生成多项式0x1021,其C代码(本文所有代码假定系统为32位,且都在VC6上编译通过)如下: unsigned short do_crc(unsigned char *message, unsigned int len)     int i, j;     unsigned short c

41、rc_reg;             crc_reg = (message0 << + message1;     for (i = 0; i < len; i+)             if (i < len - 2)           

42、  for (j = 0; j <= 7; j+)                             if (short)crc_reg < 0)              

43、0;      crc_reg = (crc_reg << 1) + (messagei + 2 >> (7 - i) 0x1021;                 else                 

44、60;   crc_reg = (crc_reg << 1) + (messagei + 2 >> (7 - i);                           else             f

45、or (j = 0; j <= 7; j+)                             if (short)crc_reg < 0)                

46、     crc_reg = (crc_reg << 1) 0x1021;                 else                     crc_reg <<= 1; 

47、;                                         return crc_reg;   显然,每次内循环的行为取决于寄存器首位。由于异或运算满足交换率和结合律,以及与0异或无影响,消息可以不移入寄存

48、器,而在每次内循环的时候,寄存器首位再与对应的消息位异或。改进的代码如下: unsigned short do_crc(unsigned char *message, unsigned int len)     int i, j;     unsigned short crc_reg = 0;     unsigned short current;             for (i = 0; i <

49、; len; i+)             current = messagei << 8;         for (j = 0; j < 8; j+)                     if (short)(crc_re

50、g current) < 0)                 crc_reg = (crc_reg << 1) 0x1021;             else              &

51、#160;  crc_reg <<= 1;             current <<= 1;                            return crc_reg; 以上的讨论中,消息的每个字节都是

52、先传输MSB,CRC16-CCITT标准却是按照先传输LSB,消息右移进寄存器来计算的。只需将代码改成判断寄存器的LSB,将0x1021按位颠倒后(0x8408)与寄存器异或即可,如下所示: Java代码 1. unsigned short do_crc(unsigned char *message, unsigned int len)    2.   3.     int i, j;   4.

53、    unsigned short crc_reg = 0;   5.     unsigned short current;   6.            7.     for (i = 0; i < len

54、; i+)    8.        9.         current = messagei;   10.         for (j = 0; j < 8; j+)    11. 

55、60;           12.             if (crc_reg  current) & 0x0001)   13.               

56、;  crc_reg = (crc_reg >> 1)  0x8408;   14.             else    15.                 crc_re

57、g >>= 1;    16.             current >>= 1;               17.            1

58、8.        19.     return crc_reg;   20.       unsigned short do_crc(unsigned char *message, unsigned int len) int i, j; unsigned short crc_reg = 0; unsigned short current; for (i = 0; i < len; i+) curre

59、nt = messagei; for (j = 0; j < 8; j+) if (crc_reg current) & 0x0001) crc_reg = (crc_reg >> 1) 0x8408; else crc_reg >>= 1; current >>= 1; return crc_reg; 该算法使用了两层循环,对消息逐位进行处理,这样效率是很低的。为了提高时间效率,通常的思想是以空间换时间。考虑到内循环只与当前的消息字节和crc_reg的低字节有关,对该算法做以下等效转换: Java代码 1. unsigned sho

60、rt do_crc(unsigned char *message, unsigned int len)    2.   3.     int i, j;   4.     unsigned short crc_reg = 0;   5.     unsigned

61、0;char  index;   6.     unsigned short to_xor;   7.           8.     for (i = 0; i < len; i+)    9.    

62、0;   10.         index = (crc_reg  messagei) & 0xff;    11.         to_xor = index;          12.  

63、60;      for (j = 0; j < 8; j+)    13.             14.             if (to_xor & 0x0

64、001)   15.                 to_xor = (to_xor >> 1)  0x8408;   16.             else    17.

65、                to_xor >>= 1;              18.            19.     

66、60;   crc_reg = (crc_reg >> 8)  to_xor;   20.        21.     return crc_reg;   22.    unsigned short do_crc(unsigned char *message, unsigned int len) int i, j;

67、 unsigned short crc_reg = 0; unsigned char index; unsigned short to_xor; for (i = 0; i < len; i+) index = (crc_reg messagei) & 0xff; to_xor = index; for (j = 0; j < 8; j+) if (to_xor & 0x0001) to_xor = (to_xor >> 1) 0x8408; else to_xor >>= 1; crc_reg = (crc_reg >> 8)

68、to_xor; return crc_reg; 现在内循环只与index相关了,可以事先以数组形式生成一个表crc16_ccitt_table,使得to_xor = crc16_ccitt_tableindex,于是可以简化为: Java代码 1. unsigned short do_crc(unsigned char *message, unsigned int len)    2.   3.     unsigned sh

69、ort crc_reg = 0;    4.              5.     while (len-)    6.         crc_reg = (crc_reg >> 8) 

70、0;crc16_ccitt_table(crc_reg  *message+) & 0xff;   7.            8.     return crc_reg;   9.      unsigned short do_crc(unsigned char *message, unsigned int

71、len) unsigned short crc_reg = 0; while (len-) crc_reg = (crc_reg >> 8) crc16_ccitt_table(crc_reg *message+) & 0xff; return crc_reg; crc16_ccitt_table通过以下代码生成: Java代码 1. int main()   2.   3.     unsigned char index = 0;  

72、 4.     unsigned short to_xor;   5.     int i;   6.   7.     printf("unsigned short crc16_ccitt_table256 =n");   8.     while (1)&

73、#160;   9.        10.         if (!(index % 8)   11.             printf("n");   12.      &

74、#160;     13.         to_xor = index;          14.         for (i = 0; i < 8; i+)    15. 

75、60;           16.             if (to_xor & 0x0001)   17.                 to_xor&#

76、160;= (to_xor >> 1)  0x8408;   18.             else    19.                 to_xor >>= 1;

77、              20.                        21.         printf("0x%04x", 

78、to_xor);   22.            23.         if (index = 255)   24.            25.         &

79、#160;   printf("n");   26.             break;   27.            28.         else  29.  

80、0;         30.             printf(", ");   31.             index+;   32.      &#

81、160;     33.        34.     printf("");   35.     return 0;   36.   37.   38. 生成的表如下:   39.   40. unsigned short crc16_ccitt_

82、table256 =   41.   42. 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,   43. 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,   44. 0x1081, 0x0108,&#

83、160;0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,   45. 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,   46. 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0

84、x55bd,   47. 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,   48. 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,   49. 0xbdcb, 0xac42, 0x9ed9, 0x8f50,&

85、#160;0xfbef, 0xea66, 0xd8fd, 0xc974,   50. 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,   51. 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,   52. 0x

86、5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,   53. 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,   54. 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab,

87、 0x0630, 0x17b9,   55. 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,   56. 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,   57. 0xffcf, 0xee46, 0

88、xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,   58. 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,   59. 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff

89、,   60. 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,   61. 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,   62. 0xa50a, 0xb483, 0x8618, 0x9791, 

90、0xe32e, 0xf2a7, 0xc03c, 0xd1b5,   63. 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,   64. 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,   65. 0x39c3,

91、 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,   66. 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,   67. 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 

92、;0x2f72, 0x3efb,   68. 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,   69. 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,   70. 0xe70e, 0xf687, 0xc41c

93、, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,   71. 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,   72. 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 

94、60; 73. 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78  74. ;  int main() unsigned char index = 0; unsigned short to_xor; int i; printf("unsigned short crc16_ccitt_table256 =n"); while (1) if (!(index % 8) printf(&

95、quot;n"); to_xor = index; for (i = 0; i < 8; i+) if (to_xor & 0x0001) to_xor = (to_xor >> 1) 0x8408; else to_xor >>= 1; printf("0x%04x", to_xor); if (index = 255) printf("n"); break; else printf(", "); index+; printf(""); return 0;生成的表如

96、下:unsigned short crc16_ccitt_table256 =0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,0x2102, 0

97、x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0

98、x36bb,0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0x

99、b8e3, 0x8a78, 0x9bf1,0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,0x9489, 0x8500, 0xb79b, 0xa

100、612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,0x39c3, 0x28

101、4a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78;这样对于消息unsi

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论