普誠創智(成都)科技有限公司-论坛

 找回密码
 立即注册
搜索
热搜: PT32 BLDCM Motor USB
查看: 49003|回复: 0
打印 上一主题 下一主题

转载:CRC16几种标准算法及其源码

[复制链接]

174

主题

198

帖子

1622

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1622
跳转到指定楼层
楼主
发表于 2022-2-7 17:43:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
CRC在线测试工具:https://www.lddgo.net/encrypt/crc

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


一、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的算法原理及程序
  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 }
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

蜀ICP备16008743号-1|普诚科技公司|小黑屋|普誠創智(成都)科技有限公司-论坛  

GMT+8, 2024-12-4 00:41 , Processed in 0.292452 second(s), 25 queries .

快速回复 返回顶部 返回列表