【转发】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. }  
[cpp]  view plain  copy
  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. }  
  26. void InvertUint32(unsigned int *dBuf,unsigned int *srcBuf)  
  27. {  
  28.     int i;  
  29.     unsigned int tmp[4];  
  30.   
  31.     tmp[0] = 0;  
  32.       
  33.     for(i=0;i< 32;i++)  
  34.     {  
  35.       if(srcBuf[0]& (1 << i))  
  36.         tmp[0]|=1<<(15 - i);  
  37.     }  
  38.     dBuf[0] = tmp[0];  
  39. }  

具体验证使用这个工具,内含CRC算法的计算,和后边的博客中提到的其他算法的工具合集

加密解密算法工具集

在这个基础上也加入CRC32 的校验算法

[html]  view plain  copy
  1. //CRC32算法:  
  2. unsigned int CRC32(unsigned char *puchMsg, unsigned int usDataLen)  
  3. {  
  4.   int i;  
  5.   unsigned int wCRCin = 0xFFFFFFFF;  
  6.   unsigned int wCPoly = 0x04C11DB7;  
  7.   unsigned int wChar = 0;  
  8.   while (usDataLen--)     
  9.   {  
  10.         wChar = *(puchMsg++);  
  11.         InvertUint8((unsigned char *)&wChar,(unsigned char *)&wChar);  
  12.         wCRCin ^= (wChar << 24);  
  13.         for(i = 0;i < 8;i++)  
  14.         {  
  15.           if(wCRCin & 0x80000000)  
  16.             wCRCin = (wCRCin << 1) ^ wCPoly;  
  17.           else  
  18.             wCRCin = wCRCin << 1;  
  19.         }  
  20.   }  
  21.   InvertUint32(&wCRCin,&wCRCin);  
  22.   return (wCRCin ^ 0xFFFFFFFF) ;  
  23. }  
对于CRC32可能还有其他的多项式和初始值和结果值是否需要异或以及输入数据是否需要位序倒转等要求在源码中修改


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值