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

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

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

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

模式

多项式

初始值

数据位序

结果处理

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+x2+1(0x8005)

0xFFFF

低位在前,高位在后

与0x0000异或

CRC16_ IBM

x16+x15+x2+1(0x8005)

0x0000

低位在前,高位在后

与0x0000异或

CRC16_ MAXIM

x16+x15+x2+1(0x8005)

0x0000

低位在前,高位在后

与0xFFFF异或

CRC16_ USB

x16+x15+x2+1(0x8005)

0xFFFF

低位在前,高位在后

与0xFFFF异或

多项式产生:
如x16+x12+x5+1
x16表示第16位为1,x5表示第5位为1
(1 << 16) | (1 << 12) | (1 << 5) | (1) = 0x11021
但是CRC16只取低16位,写成16进制数就是 0x1021

CRC16的算法原理:

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

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

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

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

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

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

unsigned short CRC16_CCITT(unsigned char *puchMsg, unsigned int usDataLen)
{unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x1021;unsigned char wChar = 0;while (usDataLen--)   {wChar = *(puchMsg++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin) ;
}
unsigned short CRC16_CCITT_FALSE(unsigned char *puchMsg, unsigned int usDataLen)
{unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x1021;unsigned char wChar = 0;while (usDataLen--)   {wChar = *(puchMsg++);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}return (wCRCin) ;
}
unsigned short CRC16_XMODEM(unsigned char *puchMsg, unsigned int usDataLen)
{unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x1021;unsigned char wChar = 0;while (usDataLen--)   {wChar = *(puchMsg++);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}return (wCRCin) ;
}unsigned short CRC16_X25(unsigned char *puchMsg, unsigned int usDataLen)
{unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x1021;unsigned char wChar = 0;while (usDataLen--)   {wChar = *(puchMsg++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin^0xFFFF) ;
}unsigned short CRC16_MODBUS(unsigned char *puchMsg, unsigned int usDataLen)
{unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x8005;unsigned char wChar = 0;while (usDataLen--)   {wChar = *(puchMsg++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin) ;
}
unsigned short CRC16_IBM(unsigned char *puchMsg, unsigned int usDataLen)
{unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x8005;unsigned char wChar = 0;while (usDataLen--)   {wChar = *(puchMsg++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin) ;
}
unsigned short CRC16_MAXIM(unsigned char *puchMsg, unsigned int usDataLen)
{unsigned short wCRCin = 0x0000;unsigned short wCPoly = 0x8005;unsigned char wChar = 0;while (usDataLen--)   {wChar = *(puchMsg++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin^0xFFFF) ;
}
unsigned short CRC16_USB(unsigned char *puchMsg, unsigned int usDataLen)
{unsigned short wCRCin = 0xFFFF;unsigned short wCPoly = 0x8005;unsigned char wChar = 0;while (usDataLen--)   {wChar = *(puchMsg++);InvertUint8(&wChar,&wChar);wCRCin ^= (wChar << 8);for(int i = 0;i < 8;i++){if(wCRCin & 0x8000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint16(&wCRCin,&wCRCin);return (wCRCin^0xFFFF) ;
}
void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf)
{int i;unsigned char tmp[4];tmp[0] = 0;for(i=0;i< 8;i++){if(srcBuf[0]& (1 << i))tmp[0]|=1<<(7-i);}dBuf[0] = tmp[0];}
void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf)
{int i;unsigned short tmp[4];tmp[0] = 0;for(i=0;i< 16;i++){if(srcBuf[0]& (1 << i))tmp[0]|=1<<(15 - i);}dBuf[0] = tmp[0];
}
void InvertUint32(unsigned int *dBuf,unsigned int *srcBuf)
{int i;unsigned int tmp[4];tmp[0] = 0;for(i=0;i< 32;i++){if(srcBuf[0]& (1 << i))tmp[0]|=1<<(15 - i);}dBuf[0] = tmp[0];
}

具体验证使用这个工具,内含CRC算法的计算,和后边的博客中提到的其他算法的工具合集

加密解密算法工具集

在这个基础上也加入CRC32 的校验算法

//CRC32算法:
unsigned int CRC32(unsigned char *puchMsg, unsigned int usDataLen)
{int i;unsigned int wCRCin = 0xFFFFFFFF;unsigned int wCPoly = 0x04C11DB7;unsigned int wChar = 0;while (usDataLen--)  {wChar = *(puchMsg++);InvertUint8((unsigned char *)&wChar,(unsigned char *)&wChar);wCRCin ^= (wChar << 24);for(i = 0;i < 8;i++){if(wCRCin & 0x80000000)wCRCin = (wCRCin << 1) ^ wCPoly;elsewCRCin = wCRCin << 1;}}InvertUint32(&wCRCin,&wCRCin);return (wCRCin ^ 0xFFFFFFFF) ;
}

对于CRC32可能还有其他的多项式和初始值和结果值是否需要异或以及输入数据是否需要位序倒转等要求在源码中修改

得到CRC16校验码的常见几个标准的算法及C语言实现相关推荐

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

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

  2. php crc16校验算法,PHP串口通信中计算crc16校验码

    最近使用PHP开发串口通信业务,在发送485Modbus命令时,基本都要计算CRC16校验码.网上搜索了很多文章,很多都计算的不对.本文记录搜索到的正确的计算方法. 代码如下:/** * crc16计 ...

  3. PHP CRC16 校验码的算法怎么使用

    PHP CRC16 校验码的算法如何使用 最近用到CRC16, 我现在就是要把 010301180001 算出CRC16的校验码,通过其他工具,可以得到 校验码是 05F1 最后完整的代码就是 010 ...

  4. 十六进制数据的CRC16校验码自写软件

    关于十六进制数据的CRC16校验码自写软件安装包 十六进制数据的CRC16校验码(0XA001)自写软件 链接与图片 全部代码 十六进制数据的CRC16校验码(0XA001)自写软件 这里分享一个自己 ...

  5. python crc-16 crc-16校验码 crc-16校验算法 ppp(MAC)帧检验序列FCS

    python crc-16 crc-16校验码 crc-16校验算法 ppp(MAC)帧检验序列FCS 想弄明白这里要看多几遍,配合下面的例子能更快理解. 第一.CRC-16校验码计算方法: 常用查表 ...

  6. java计算CRC16校验码

    java计算校验码的一个公式,亲测可行有效 /*** 计算CRC16校验码** @param data 需要校验的字符串* @return 校验码*/public static String getC ...

  7. CRC16校验码生成原理

    CRC16-Modbus 生成多项式为CRC-16 : X16 + X15 + X2 + 1  对应 0x8005 移位寄存器初始化值为0xFFFF 算法说明: 1) 设置CRC寄存器初始值0xFFF ...

  8. 常用crc查表法_CRC校验码简介及CRC16的计算方法

    点击上方"嵌入式从0到1",选择"置顶/星标公众号" 干货福利,第一时间送达! 什么是CRC校验? CRC即循环冗余校验码(Cyclic Redundancy ...

  9. crc16校验c语言程序源码,CRC16代码(C语言实现)

    Modbus CRC16校验代码 嵌入式系统crc16校验码计算函数记录 /************************************************** * CRC 高位字节值 ...

最新文章

  1. “金主爸爸快回来交学费吧!”疫情让中国留学生难以返校,国外高校面临资金短缺...
  2. pytorch nan解决方法笔记
  3. 【SpringMVC框架】springmvc的基础知识
  4. 51—Nod 1384 全排列
  5. C/C++基础一:stack heap
  6. CenterNet :Objects as Points/CenterTrack:Tracking Objects as Points
  7. 整理下关于Visual Foxpro的技术
  8. phpQuery采集乱码问题解决方案
  9. 怎么恢复佳能相机SD卡CF卡误删除格式化的MOV视频
  10. 为什么哪些90后程序员年薪50万+,他们经历了啥?
  11. 分享一些自己在用的maccms10的免费采集接口
  12. 获取多边形的最大最小坐标
  13. html5车牌效果,html中车牌号省份简称输入键盘的示例代码
  14. Matlab点云处理及可视化第1期—基于KD树的邻域点搜索(柱状邻域、球状邻域及KNN)
  15. word标尺灰色_如何在Microsoft Word中使用标尺
  16. 学计算机电脑显存多少为好,【深度分析】如何配置深度学习用的电脑(显卡和内存的选择标准)...
  17. vim中删除当前行后面所有的行
  18. Atmel推出业内首款面向智能能源和自动化应用的IEEE 802.15.4g-2012双频段收发器
  19. 谷歌的招聘 (20分)
  20. 传递矩阵的特征多项式

热门文章

  1. bool 字符串方法 和for循环
  2. 今日浅谈循环 for与while
  3. Action访问Servlet API的三种方法
  4. 加解压开源组件-SharpZipLib
  5. foreach 语句
  6. 记下来 关于InitCommonControls()
  7. SourceTree的基本使用
  8. Linux C Socket编程原理及简单实例
  9. HttpClient+jsoup登录+解析 163邮箱
  10. 解决Fckeditor删除所有上传页面如何上传