MODBUS模型下CRC-16校验C/C++程序实现

这篇具有很好参考价值的文章主要介绍了MODBUS模型下CRC-16校验C/C++程序实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

看了很多相关博客,例如http://t.csdn.cn/Ek3RV

又例如http://t.csdn.cn/HGUmo

这些文章所提供的代码似乎都是没有错误的,但很多文章的文字描述和代码并不对应。因此我也整理了一下,也当做是给自己做个笔记。

CRC校验按位计算的程序很好理解,写起来也比较简单,就是把模二除法的过程整个描述一遍。但本人认为查表程序看起来还是有一定迷惑性的,因此接下来提供查表程序的相关代码和原理性介绍。

查表程序总的来说就是对按位计算算法的循环(以一个字节为单位)。

需要注意的是,CRC校验有多种模型,每种模型对应的程序源代码会有些许改动,但CRC表是不变的。具体可以参考CRC在线计算网站CRC(循环冗余校验)在线计算_ip33.com的说明。

crc16校验程序,c++,c语言,开发语言,网络协议,算法

crc16校验程序,c++,c语言,开发语言,网络协议,算法

crc16校验程序,c++,c语言,开发语言,网络协议,算法

 以下为C/C++程序代码,程序结果与第一张图网站计算的保持一致。

/*
步骤(以CRC16-MODBUS模型为例,多项式Poly = 0x8005)
1.设置CRC寄存器,并给其赋初值FFFF(hex)。
2.将数据的第一个8bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC寄存器。
3.CRC寄存器向右移一位,MSB补零,并检查移出的LSB。
4.如果LSB为0,重复第3步;若LSB为1,CRC寄存器与多项式码相异或。
5.重复第3与第4步直到8次移位全部完成。此时一个8bit数据处理完毕。
6.重复第2至第5步直到所有数据全部字节数据处理完成。
7. 将该通讯信息帧所有字节按上述步骤计算完成后,即可得到16位CRC寄存器的高、低
   字节。
8.最终CRC寄存器的内容即为CRC值,注意本程序CRC值高位在左,低位在右。
————————————————
在线计算网址  http://www.ip33.com/crc.html
*/

#include <iostream>
using namespace std;

typedef uint8_t uchar;
typedef uint16_t ushort;
ushort usMBCRC16(uchar *, ushort);//CRC函数声明

//查找表如下
static const uchar aucCRCHi[] = 
{
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
	0x00, 0xC1, 0x81, 0x40
};
static const uchar aucCRCLo[] = 
{
	0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
	0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
	0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
	0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
	0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
	0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
	0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
	0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
	0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
	0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
	0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
	0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
	0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
	0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
	0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
	0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
	0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
	0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
	0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
	0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
	0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
	0x41, 0x81, 0x80, 0x40
};

ushort usMBCRC16(uchar * pucFrame, ushort usLen)//pucFrame=指向数据首字节的指针,usLen=数据字节数
{
	uchar ucCRCHi = 0xFF;
	uchar ucCRCLo = 0xFF;//初始化CRC寄存器为0xFFFF
	int iIndex;
	while (usLen--)
	{
		iIndex = ucCRCLo ^ *(pucFrame++);//第一次为初始化,使数据的首字节与CRC寄存器低八位异或后存入临时寄存器
										 //iIndex即为CRC表格索引
		ucCRCLo = ucCRCHi ^ aucCRCHi[iIndex];//查表,将第i次的iIndex值在高字节CRC查找表中找到,
											 //并与CRC寄存器高字节按位异或后,值赋给CRC低字节寄存器
		ucCRCHi = aucCRCLo[iIndex];//查表,将第i次的iIndex值在低字节CRC查找表中找到,并赋值给CRC高字节寄存器
	}
	//当所有字节都执行完毕后,返回CRC寄存器中的高低字节数值,即为最终CRC数值。
	return (ushort)(ucCRCHi << 8 | ucCRCLo);//CRC高位在左,低位在右
}

//主函数
int main()
{
	uchar str[] = { 0X00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
	                0x0B, 0x0C, 0x0D, 0x0E, 0x0F};//传输的原始数据
	ushort strl = sizeof(str);       //数据所包含的字节数
	cout << "Byte : " << dec << strl << endl;
	cout << "CRC  : " << "0x" << hex << usMBCRC16(str,strl) << endl;
	system("pause");
}

 运行结果如图

crc16校验程序,c++,c语言,开发语言,网络协议,算法文章来源地址https://www.toymoban.com/news/detail-599635.html

到了这里,关于MODBUS模型下CRC-16校验C/C++程序实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言CRC-16 CCITT-FALSE格式校验函数

    CRC-16校验产生2个字节长度的数据校验码,通过计算得到的校验码和获得的校验码比较,用于验证获得的数据的正确性。基本的CRC-16校验算法实现,参考: C语言标准CRC-16校验函数。 不同应用规范通过对输入数据前处理和输出数据后处理的方式不同,又产生了不同的应用规范校

    2024年02月12日
    浏览(47)
  • CRC校验(模型、手算、程序编写)

    一.模型 1.WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位 2.REFIN:true或false,如为true输入的原始数据的每个字节需要做个逆序的处理,注意:针对的每个字节,而不是整个数据, 举例如下: 以一个4字节的原始数据为例: 3.INIT:这是算法开始时寄存器(crc)的初始

    2024年02月07日
    浏览(37)
  • C#: CRC8,CRC16,CRC32 校验代码

    说明:CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似

    2024年01月18日
    浏览(39)
  • CRC校验码生成逻辑的实现原理详解——结合C语言和Verilog语言代码分析

    因为前段时间用到CRC校验码,所以在网上找到了很多有关CRC校验码计算原理以及生成CRC校验码的代码实现(包括C语言和Verilog语言的实现)的文章,但关于CRC校验码代码实现的原理未能找到相关文章,于是自己结合C语言和Veirlog语言的实现代码以及CRC校验码的计算原理,对CR

    2023年04月22日
    浏览(99)
  • CRC校验(2):CRC32查表法详解、代码实现及CRC反转

    对于现在的CPU来说,基本上都在硬件上实现了CRC校验。但我们还是想用软件来实现一下CRC的代码,这样可以更深入地理解里面的原理。所以这一节就来详细地解释如何使用查表法从软件上来实现CRC-32的校验。另外,CRC还有一种反转的情况,实际上反转和不反转没有什么太大的

    2024年02月09日
    浏览(211)
  • C语言CRC-32 STM32格式校验函数

    CRC-32校验产生4个字节长度的数据校验码,通过计算得到的校验码和获得的校验码比较,用于验证获得的数据的正确性。基本的CRC-32校验算法实现,参考: C语言标准CRC-32校验函数 不同厂家通过对输入数据前处理和输出数据后处理的方式不同,又产生了不同的厂家校验函数,这

    2023年04月27日
    浏览(54)
  • C# | 上位机开发新手指南(五)校验算法——CRC

    当我们在进行数据传输时,可能会因为信道噪声、干扰等因素导致数据出现错误,从而影响传输的可靠性和准确性。此时,我们需要一种方法来检测数据是否出现错误,并尽可能快速地发现和纠正错误。CRC(Cyclic Redundancy Check)校验算法就是一种常用的数据校验方法,它通过

    2024年01月18日
    浏览(54)
  • CRC校验码详解+Verilog实现(含代码)

    目录 CRC码简介 CRC校验码生成步骤  CRC码生成多项式  CRC校验码Verilog实现 CRC即循环冗余校验,是一种数字通信中的常用信道编码技术。其特征是信息段和校验字段的长度可以任意选定 CRC码是由2部分组成的,前部分是信息码,后部分是校验码,如果CRC码长共 n bit,信息码长

    2023年04月08日
    浏览(43)
  • 十六、基于FPGA的CRC校验设计实现

    循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。 多项式一般指输入数据异或的对象;其

    2023年04月24日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包