CRC16常见几个标准的算法及C语言实现

CRC16常见的标准有以下几种,被用在各个规范中,其算法原理基本一致,就是在数据的输入和输出有所差异,下边把这些标准的差异列出,并给出C语言的算法实现。

CRC16_CCITT:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,高位在后,结果与0x0000异或

CRC16_CCITT_FALSE:多项式x16+x12+x5+1(0x1021),初始值0xFFFF,低位在后,高位在前,结果与0x0000异或

CRC16_XMODEM:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在后,高位在前,结果与0x0000异或

CRC16_X25:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,高位在后,结果与0xFFFF异或

CRC16_MODBUS:多项式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,高位在后,结果与0x0000异或

CRC16_IBM:多项式x16+x15+x2+1(0x8005),初始值0x0000,低位在前,高位在后,结果与0x0000异或

CRC16_MAXIM:多项式x16+x15+x2+1(0x8005),初始值0x0000,低位在前,高位在后,结果与0xFFFF异或

CRC16_USB:多项式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,高位在后,结果与0xFFFF异或

模式

多项式

初始值

数据位序

结果处理

CRC16_CCITT

x16+x12+x5+1(0x1021)

0x0000

低位在前,高位在后

与0x0000异或

CRC16_CCITT_FALSE

x16+x12+x5+1(0x1021)

0xFFFF

低位在后,高位在前

与0x0000异或

CRC16_XMODEM

x16+x12+x5+1(0x1021)

0x0000

低位在后,高位在前

与0x0000异或

CRC16_X25

x16+x12+x5+1(0x1021)

0x0000

低位在后,高位在前

与0xFFFF异或

CRC16_ MODBUS

x16+x15+x2+1(0x8005)

0xFFFF

低位在前,高位在后

与0x0000异或

CRC16_ IBM

x16+x15+x2+1(0x8005)

0x0000

低位在前,高位在后

与0x0000异或

CRC16_ MAXIM

x16+x15+x2+1(0x8005)

0x0000

低位在前,高位在后

与0xFFFF异或

CRC16_ USB

x16+x15+x2+1(0x8005)

0xFFFF

低位在前,高位在后

与0xFFFF异或

多项式产生:
如x16+x12+x5+1
x16表示第16位为1,x5表示第5位为1
(1 << 16) | (1 << 12) | (1 << 5) | (1) = 0x11021
但是CRC16只取低16位,写成16进制数就是 0x1021

CRC16的算法原理:

1.根据CRC16的标准选择初值CRCIn的值。

2.将数据的第一个字节与CRCIn高8位异或。

3.判断最高位,若该位为 0 左移一位,若为 1 左移一位再与多项式Hex码异或。

4.重复3直至8位全部移位计算结束。

5.重复将所有输入数据操作完成以上步骤,所得16位数即16位CRC校验码。

根据算法原理与标准要求就能简单的写出具体程序:

 
  1. unsigned short CRC16_CCITT(unsigned char *puchMsg, unsigned int usDataLen)

  2. {

  3. unsigned short wCRCin = 0x0000;

  4. unsigned short wCPoly = 0x1021;

  5. unsigned char wChar = 0;

  6.  
  7. while (usDataLen--)

  8. {

  9. wChar = *(puchMsg++);

  10. InvertUint8(&wChar,&wChar);

  11. wCRCin ^= (wChar << 8);

  12. for(int i = 0;i < 8;i++)

  13. {

  14. if(wCRCin & 0x8000)

  15. wCRCin = (wCRCin << 1) ^ wCPoly;

  16. else

  17. wCRCin = wCRCin << 1;

  18. }

  19. }

  20. InvertUint16(&wCRCin,&wCRCin);

  21. return (wCRCin) ;

  22. }

  23. unsigned short CRC16_CCITT_FALSE(unsigned char *puchMsg, unsigned int usDataLen)

  24. {

  25. unsigned short wCRCin = 0xFFFF;

  26. unsigned short wCPoly = 0x1021;

  27. unsigned char wChar = 0;

  28.  
  29. while (usDataLen--)

  30. {

  31. wChar = *(puchMsg++);

  32. wCRCin ^= (wChar << 8);

  33. for(int i = 0;i < 8;i++)

  34. {

  35. if(wCRCin & 0x8000)

  36. wCRCin = (wCRCin << 1) ^ wCPoly;

  37. else

  38. wCRCin = wCRCin << 1;

  39. }

  40. }

  41. return (wCRCin) ;

  42. }

  43. unsigned short CRC16_XMODEM(unsigned char *puchMsg, unsigned int usDataLen)

  44. {

  45. unsigned short wCRCin = 0x0000;

  46. unsigned short wCPoly = 0x1021;

  47. unsigned char wChar = 0;

  48.  
  49. while (usDataLen--)

  50. {

  51. wChar = *(puchMsg++);

  52. wCRCin ^= (wChar << 8);

  53. for(int i = 0;i < 8;i++)

  54. {

  55. if(wCRCin & 0x8000)

  56. wCRCin = (wCRCin << 1) ^ wCPoly;

  57. else

  58. wCRCin = wCRCin << 1;

  59. }

  60. }

  61. return (wCRCin) ;

  62. }

  63.  
  64. unsigned short CRC16_X25(unsigned char *puchMsg, unsigned int usDataLen)

  65. {

  66. unsigned short wCRCin = 0xFFFF;

  67. unsigned short wCPoly = 0x1021;

  68. unsigned char wChar = 0;

  69.  
  70. while (usDataLen--)

  71. {

  72. wChar = *(puchMsg++);

  73. InvertUint8(&wChar,&wChar);

  74. wCRCin ^= (wChar << 8);

  75. for(int i = 0;i < 8;i++)

  76. {

  77. if(wCRCin & 0x8000)

  78. wCRCin = (wCRCin << 1) ^ wCPoly;

  79. else

  80. wCRCin = wCRCin << 1;

  81. }

  82. }

  83. InvertUint16(&wCRCin,&wCRCin);

  84. return (wCRCin^0xFFFF) ;

  85. }

  86.  
  87. unsigned short CRC16_MODBUS(unsigned char *puchMsg, unsigned int usDataLen)

  88. {

  89. unsigned short wCRCin = 0xFFFF;

  90. unsigned short wCPoly = 0x8005;

  91. unsigned char wChar = 0;

  92.  
  93. while (usDataLen--)

  94. {

  95. wChar = *(puchMsg++);

  96. InvertUint8(&wChar,&wChar);

  97. wCRCin ^= (wChar << 8);

  98. for(int i = 0;i < 8;i++)

  99. {

  100. if(wCRCin & 0x8000)

  101. wCRCin = (wCRCin << 1) ^ wCPoly;

  102. else

  103. wCRCin = wCRCin << 1;

  104. }

  105. }

  106. InvertUint16(&wCRCin,&wCRCin);

  107. return (wCRCin) ;

  108. }

  109. unsigned short CRC16_IBM(unsigned char *puchMsg, unsigned int usDataLen)

  110. {

  111. unsigned short wCRCin = 0x0000;

  112. unsigned short wCPoly = 0x8005;

  113. unsigned char wChar = 0;

  114.  
  115. while (usDataLen--)

  116. {

  117. wChar = *(puchMsg++);

  118. InvertUint8(&wChar,&wChar);

  119. wCRCin ^= (wChar << 8);

  120. for(int i = 0;i < 8;i++)

  121. {

  122. if(wCRCin & 0x8000)

  123. wCRCin = (wCRCin << 1) ^ wCPoly;

  124. else

  125. wCRCin = wCRCin << 1;

  126. }

  127. }

  128. InvertUint16(&wCRCin,&wCRCin);

  129. return (wCRCin) ;

  130. }

  131. unsigned short CRC16_MAXIM(unsigned char *puchMsg, unsigned int usDataLen)

  132. {

  133. unsigned short wCRCin = 0x0000;

  134. unsigned short wCPoly = 0x8005;

  135. unsigned char wChar = 0;

  136.  
  137. while (usDataLen--)

  138. {

  139. wChar = *(puchMsg++);

  140. InvertUint8(&wChar,&wChar);

  141. wCRCin ^= (wChar << 8);

  142. for(int i = 0;i < 8;i++)

  143. {

  144. if(wCRCin & 0x8000)

  145. wCRCin = (wCRCin << 1) ^ wCPoly;

  146. else

  147. wCRCin = wCRCin << 1;

  148. }

  149. }

  150. InvertUint16(&wCRCin,&wCRCin);

  151. return (wCRCin^0xFFFF) ;

  152. }

  153. unsigned short CRC16_USB(unsigned char *puchMsg, unsigned int usDataLen)

  154. {

  155. unsigned short wCRCin = 0xFFFF;

  156. unsigned short wCPoly = 0x8005;

  157. unsigned char wChar = 0;

  158.  
  159. while (usDataLen--)

  160. {

  161. wChar = *(puchMsg++);

  162. InvertUint8(&wChar,&wChar);

  163. wCRCin ^= (wChar << 8);

  164. for(int i = 0;i < 8;i++)

  165. {

  166. if(wCRCin & 0x8000)

  167. wCRCin = (wCRCin << 1) ^ wCPoly;

  168. else

  169. wCRCin = wCRCin << 1;

  170. }

  171. }

  172. InvertUint16(&wCRCin,&wCRCin);

  173. return (wCRCin^0xFFFF) ;

  174. }

 
  1. void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf)

  2. {

  3. int i;

  4. unsigned char tmp[4];

  5. tmp[0] = 0;

  6. for(i=0;i< 8;i++)

  7. {

  8. if(srcBuf[0]& (1 << i))

  9. tmp[0]|=1<<(7-i);

  10. }

  11. dBuf[0] = tmp[0];

  12.  
  13. }

  14. void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf)

  15. {

  16. int i;

  17. unsigned short tmp[4];

  18. tmp[0] = 0;

  19. for(i=0;i< 16;i++)

  20. {

  21. if(srcBuf[0]& (1 << i))

  22. tmp[0]|=1<<(15 - i);

  23. }

  24. dBuf[0] = tmp[0];

  25. }

具体验证请使用这个工具,内含CRC所有算法的计算

你可能感兴趣的:(c)