【轉】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 } 

 

來源


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM