普誠創智(成都)科技有限公司-论坛
标题:
转载:CRC16几种标准算法及其源码
[打印本页]
作者:
James_Jiang
时间:
2022-2-7 17:43
标题:
转载:CRC16几种标准算法及其源码
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 }
欢迎光临 普誠創智(成都)科技有限公司-论坛 (https://princeton.com.cn/)
Powered by Discuz! X3.2