一、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://www.cnblogs.com/skullboyer/p/8342167.html

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

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

    一.CRC16校验码的使用 现选择最常用的CRC-16校验,说明它的使用方法. 根据Modbus协议,常规485通讯的信息发送形式如下: 地址 功能码 数据信息 校验码 1byte 1byte nby ...

  2. C 语言 crc16校验算法,CRC16的标准校验算法及C语言实现(附代码)

    原标题:CRC16的标准校验算法及C语言实现(附代码) CRC码由发送端计算,放置于发送信息报文的尾部.接收信息的设备再重新计算接收到信息报文的CRC,比较计算得到的CRC是否与接收到的相符,如果两者 ...

  3. c语言程序位置式pid算法,位置式PID算法的C语言代码

    描述 位置式PID的C语言写法详解 PID调节口诀: 参数整定找最佳,从小到大顺序查 先是比例后积分,最后再把微分加 曲线振荡很频繁,比例度盘要放大 曲线漂浮绕大湾,比例度盘往小扳 曲线偏离回复慢,积 ...

  4. 字体识别c语言,OCR算法之C语言代码 - 源码下载|图形图象|图形/文字识别|源代码 - 源码中国...

    OCR算法代码. 这不是一个完整的系统,没法生成可执行程序. 代码基于Linux/KDE开发,用到了C++标准模板库. 代码的目的是向读者展示一个OCR系统包括哪些部分,如何工作, 读者可以借鉴这些代 ...

  5. 卡尔曼滤波算法及c语言代码,卡尔曼滤波算法及C语言代码

    卡尔曼滤波算法及C语言代码 卡尔曼滤波简介及其算法实现代码 卡尔曼滤波算法实现代码(C,C++分别实现) 卡尔曼滤波器简介 近来发现有些问题很多人都很感兴趣.所以在这里希望能尽自己能力跟大家讨论一些力 ...

  6. c语言多组数据判断回文字符串,详解判断回文字符串跟回文数算法的C语言代码...

    详解判断回文字符串和回文数算法的C语言代码! 一.判断一个字符串是否为回文字符串 #include #include #include //包含strlen #define YES 1 #define ...

  7. 得到CRC16校验码的常见几个标准的算法及C语言实现

    CRC16常见的标准有以下几种,被用在各个规范中,其算法原理基本一致,就是在数据的输入和输出有所差异,下边把这些标准的差异列出,并给出C语言的算法实现. CRC16_CCITT:多项式x16+x12+ ...

  8. crc16 ibm c语言,CRC16常见几个标准的算法及C语言实现

    CRC码由发送端计算,放置于发送信息报文的尾部.接收信息的设备再重新计算接收到信息报文的CRC,比较计算得到的CRC是否与接收到的相符,如果两者不相符,则表明出错. 校验码的计算多项式为(X16 + ...

  9. 一文详解循环冗余校验校验算法(CRC校验)及C语言代码的实现 ---- 以CRC-16/MODBUS为例讲解

    一.概述 现在的产品开发过程中,无论是数据的储存还是传输,都需要确保数据的准确性,所以就需要在数据帧后面附加一串校验码,方便接收方使用校验码校验接收到的数据是否是正确的. 常用的校验方式有奇偶校验.异 ...

  10. CRC-16标准校验算法

    转载:http://blog.sina.com.cn/s/blog_c5c2bd470102vfhf.html 错误校验(CRC)域占用两个字节,包含了一个16位的二进制值.CRC值由传输设备计算出来 ...

最新文章

  1. 团队实践,我们是怎么用敏捷开发工具Leangoo的
  2. CentOS 7 单用户模式+救援模式
  3. [转]自适应网页设计(Responsive Web Design)
  4. oracle 中的常用exception
  5. 使用Docker-容器命令介绍
  6. vs+opencv编译出现内存问题
  7. 浅入浅出 Android 安全 翻译完成!
  8. bug-Both weights and assigned values must be a sequence of numbers when assigning to values of <clas
  9. java中是否可以覆盖over_”static”关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static的方法?...
  10. sqlplus连接Oracle的正确语法
  11. NFR24C0L中文使用手册、stm32硬件SPI与模拟SPI比较:
  12. 复杂网络理论及其应用-基本概念
  13. RFID:ISO14443、15693、18000体系分析
  14. php 中标麒麟龙芯5.0,中标麒麟桌面操作系统软件
  15. 利用go破解带密码的rar压缩文件
  16. 完美解决浏览器劫持方法,简单实用百试百灵!
  17. unity3d 中添加视频
  18. 技术人才的出路在哪里,5种选择和2种思路
  19. Intel_IPP 的基本使用方法
  20. 两分钟研究透idea中Git文件的颜色,绿红蓝白灰

热门文章

  1. Mac 安装 valet
  2. UTM 用户线程模型
  3. Java开发中学用eclipse code templates
  4. 读取文件的例子 IO
  5. 熔断与降级 搜索和学习 了解不深
  6. 三天两夜肝完这篇万字长文,终于拿下了 TCP/IP
  7. 【系统架构】如何逐步去构建一个大型网站系统
  8. 分布式MySQL集群方案,看看京东是怎么做的
  9. 想做视频号,先纠正一点
  10. 联合 5 位大佬送 210 本实体书,包邮到家!