【转】crc16几种标准校验算法及c语言代码

一、CRC16校验码的使用

  现选择最常用的CRC-16校验,说明它的使用方法。

  根据Modbus协议,常规485通讯的信息发送形式如下:

  地址 功能码 数据信息 校验码

  1byte 1byte nbyte 2byte

  CRC校验是前面几段数据内容的校验值,为一个16位数据,发送时,低8位在前,高8为最后。

  例如:信息字段代码为: 1011001,校验字段为:1010。

  发送方:发出的传输字段为: 1 0 1 1 0 0 1 1 0 10

  信息字段 校验字段

  接收方:使用相同的计算方法计算出信息字段的校验码,对比接收到的实际校验码,如果相等及信息正确,不相等则信息错误;或者将接受到的所有信息除多项式,如果能够除尽,则信息正确。

二、CRC16校验码计算方法

  常用查表法和计算法。计算方法一般都是:

  (1)、预置1个16位的寄存器值0xFFFF,称此寄存器为CRC寄存器;

  (2)、把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低

  8位相异或,把结果放于CRC寄存器,高八位数据不变;

  (3)、把CRC寄存器的内容右移一位(朝高位)用0填补最高位,并检查右移后的移出位;

  (4)、如果移出位为0:重复第3步(再次右移一位);如果移出位为1,CRC寄存器与一多

  项式(A001)进行异或;

  (5)、重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;

  (6)、重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;

  (7)、将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低

  字节进行交换;

  (8)、最后得到的CRC寄存器内容即为:CRC码。

  以上计算步骤中的多项式A001是8005按位颠倒后的结果。

  查表法是将移位异或的计算结果做成了一个表,就是将0~256放入一个长度为16位的寄存器中的低八位,高八位填充0,然后将该寄存器与多项式0XA001按照上述3、4步骤,直到八位全部移出,最后寄存器中的值就是表格中的数据,高八位、低八位分别单独一个表。

三、CRC16常见几个标准的算法

  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+x5+1(0x8005),初始值0xFFFF,低位在前,高位在后,结果与0x0000异或

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

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

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

crc16几种标准校验算法及c语言代码

四、CRC16的算法原理及程序

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

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

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

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

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

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

  1 /**
  2 **************************************************************************************************
  3 * @Brief    Single byte data inversion        
  4 * @Param    
  5 *            @DesBuf: destination buffer
  6 *            @SrcBuf: source buffer
  7 * @RetVal    None
  8 * @Note      (MSB)0101_0101 ---> 1010_1010(LSB)
  9 **************************************************************************************************
 10 */
 11 void InvertUint8(unsigned char *DesBuf, unsigned char *SrcBuf)
 12 {
 13     int i;
 14     unsigned char temp = 0;
 15     
 16     for(i = 0; i < 8; i++)
 17     {
 18         if(SrcBuf[0] & (1 << i))
 19         {
 20             temp |= 1<<(7-i);
 21         }
 22     }
 23     DesBuf[0] = temp;
 24 }
 25 
 26 /**
 27 **************************************************************************************************
 28 * @Brief    double byte data inversion        
 29 * @Param    
 30 *            @DesBuf: destination buffer
 31 *            @SrcBuf: source buffer
 32 * @RetVal    None
 33 * @Note      (MSB)0101_0101_1010_1010 ---> 0101_0101_1010_1010(LSB)
 34 **************************************************************************************************
 35 */
 36 void InvertUint16(unsigned short *DesBuf, unsigned short *SrcBuf)  
 37 {  
 38     int i;  
 39     unsigned short temp = 0;    
 40     
 41     for(i = 0; i < 16; i++)  
 42     {  
 43         if(SrcBuf[0] & (1 << i))
 44         {          
 45             temp |= 1<<(15 - i);  
 46         }
 47     }  
 48     DesBuf[0] = temp;  
 49 }
 50 
 51 unsigned short CRC16_CCITT(unsigned char *puchMsg, unsigned int usDataLen)  
 52 {  
 53     unsigned short wCRCin = 0x0000;  
 54     unsigned short wCPoly = 0x1021;  
 55     unsigned char wChar = 0;  
 56     
 57     while (usDataLen--)     
 58     {  
 59         wChar = *(puchMsg++);  
 60         InvertUint8(&wChar, &wChar);  
 61         wCRCin ^= (wChar << 8); 
 62         
 63         for(int i = 0; i < 8; i++)  
 64         {  
 65             if(wCRCin & 0x8000)
 66             {
 67                 wCRCin = (wCRCin << 1) ^ wCPoly; 
 68             }            
 69             else 
 70             {              
 71                 wCRCin = wCRCin << 1;  
 72             }
 73         }  
 74     }  
 75     InvertUint16(&wCRCin, &wCRCin);  
 76     return (wCRCin) ;  
 77 } 
 78  
 79 unsigned short CRC16_CCITT_FALSE(unsigned char *puchMsg, unsigned int usDataLen)  
 80 {  
 81     unsigned short wCRCin = 0xFFFF;  
 82     unsigned short wCPoly = 0x1021;  
 83     unsigned char wChar = 0;  
 84     
 85     while (usDataLen--)     
 86     {  
 87         wChar = *(puchMsg++);  
 88         wCRCin ^= (wChar << 8); 
 89         
 90         for(int i = 0; i < 8; i++)  
 91         {  
 92             if(wCRCin & 0x8000)  
 93             {
 94                 wCRCin = (wCRCin << 1) ^ wCPoly;  
 95             }
 96             else  
 97             {
 98                 wCRCin = wCRCin << 1; 
 99             }            
100         }  
101     }  
102     return (wCRCin) ;  
103 }  
104 
105 unsigned short CRC16_XMODEM(unsigned char *puchMsg, unsigned int usDataLen)  
106 {  
107     unsigned short wCRCin = 0x0000;  
108     unsigned short wCPoly = 0x1021;  
109     unsigned char wChar = 0;  
110     
111     while (usDataLen--)     
112     {  
113         wChar = *(puchMsg++);  
114         wCRCin ^= (wChar << 8);
115         
116         for(int i = 0; i < 8; i++)  
117         {  
118             if(wCRCin & 0x8000)  
119             {
120                 wCRCin = (wCRCin << 1) ^ wCPoly;  
121             }
122             else
123             {              
124                 wCRCin = wCRCin << 1;
125             }
126         }  
127     }  
128     return (wCRCin) ;  
129 }  
130   
131 unsigned short CRC16_X25(unsigned char *puchMsg, unsigned int usDataLen)  
132 {  
133     unsigned short wCRCin = 0xFFFF;  
134     unsigned short wCPoly = 0x1021;  
135     unsigned char wChar = 0;  
136     
137     while (usDataLen--)     
138     {  
139         wChar = *(puchMsg++);  
140         InvertUint8(&wChar, &wChar);  
141         wCRCin ^= (wChar << 8); 
142         
143         for(int i = 0;i < 8;i++)  
144         {  
145             if(wCRCin & 0x8000)
146             {              
147                 wCRCin = (wCRCin << 1) ^ wCPoly; 
148             }            
149             else  
150             {
151                 wCRCin = wCRCin << 1; 
152             }            
153         }  
154     }  
155     InvertUint16(&wCRCin, &wCRCin);  
156     return (wCRCin^0xFFFF) ;  
157 }  
158   
159 unsigned short CRC16_MODBUS(unsigned char *puchMsg, unsigned int usDataLen)  
160 {  
161     unsigned short wCRCin = 0xFFFF;  
162     unsigned short wCPoly = 0x8005;  
163     unsigned char wChar = 0;  
164     
165     while (usDataLen--)     
166     {  
167         wChar = *(puchMsg++);  
168         InvertUint8(&wChar, &wChar);  
169         wCRCin ^= (wChar << 8); 
170         
171         for(int i = 0; i < 8; i++)  
172         {  
173             if(wCRCin & 0x8000) 
174             {
175                 wCRCin = (wCRCin << 1) ^ wCPoly;  
176             }
177             else  
178             {
179                 wCRCin = wCRCin << 1; 
180             }            
181         }  
182     }  
183     InvertUint16(&wCRCin, &wCRCin);  
184     return (wCRCin) ;  
185 } 
186  
187 unsigned short CRC16_IBM(unsigned char *puchMsg, unsigned int usDataLen)  
188 {  
189     unsigned short wCRCin = 0x0000;  
190     unsigned short wCPoly = 0x8005;  
191     unsigned char wChar = 0;  
192     
193     while (usDataLen--)     
194     {  
195         wChar = *(puchMsg++);  
196         InvertUint8(&wChar, &wChar);  
197         wCRCin ^= (wChar << 8);  
198         
199         for(int i = 0; i < 8; i++)  
200         {  
201             if(wCRCin & 0x8000)  
202             {
203                 wCRCin = (wCRCin << 1) ^ wCPoly; 
204             }            
205             else  
206             {
207                 wCRCin = wCRCin << 1;  
208             }
209         }  
210     }  
211     InvertUint16(&wCRCin,&wCRCin);  
212     return (wCRCin) ;  
213 }  
214 
215 unsigned short CRC16_MAXIM(unsigned char *puchMsg, unsigned int usDataLen)  
216 {  
217     unsigned short wCRCin = 0x0000;  
218     unsigned short wCPoly = 0x8005;  
219     unsigned char wChar = 0;  
220     
221     while (usDataLen--)     
222     {  
223         wChar = *(puchMsg++);  
224         InvertUint8(&wChar, &wChar);  
225         wCRCin ^= (wChar << 8);  
226         
227         for(int i = 0; i < 8; i++)  
228         {  
229             if(wCRCin & 0x8000) 
230             {              
231                 wCRCin = (wCRCin << 1) ^ wCPoly;
232             }
233             else 
234             {              
235                 wCRCin = wCRCin << 1;  
236             }
237         }  
238     }  
239     InvertUint16(&wCRCin, &wCRCin);  
240     return (wCRCin^0xFFFF) ;  
241 }  
242 
243 unsigned short CRC16_USB(unsigned char *puchMsg, unsigned int usDataLen)  
244 {  
245     unsigned short wCRCin = 0xFFFF;  
246     unsigned short wCPoly = 0x8005;  
247     unsigned char wChar = 0;  
248     
249     while (usDataLen--)     
250     {  
251         wChar = *(puchMsg++);  
252         InvertUint8(&wChar, &wChar);  
253         wCRCin ^= (wChar << 8); 
254         
255         for(int i = 0; i < 8; i++)  
256         {  
257             if(wCRCin & 0x8000) 
258             {              
259                 wCRCin = (wCRCin << 1) ^ wCPoly;
260             }            
261             else  
262             {
263                 wCRCin = wCRCin << 1; 
264             }            
265         }  
266     }  
267     InvertUint16(&wCRCin, &wCRCin);  
268     return (wCRCin^0xFFFF) ;  
269 } 

 

来源

转载于:https://www.cnblogs.com/skullboyer/p/8342167.html

你可能感兴趣的:(【转】crc16几种标准校验算法及c语言代码)