Modbus CRC16校验方法及实现代码

0.前言

项目中所用到的DI数字开关模块通信方式为串口通信,内置数据校验方式为Modbus CRC16。
Modbus CRC16校验方法及实现代码_第1张图片
这种校验方式第一次遇到,于是百度了一下,找到这篇文章,按照步骤,自己写了下代码,对比了下文中代码,基本一样。

1.实现步骤及代码

实现步骤

Modbus CRC16校验方法及实现代码_第2张图片

代码实现
#include
#include 
using namespace std;
int main()
{
	unsigned short CRC = 0xffff;//(1)CRC寄存器初值0xffff
	unsigned char data[6] = { 0x01,0x03,0x61,0x00,0x00,0x02 };//待校验的数据

	for (int i = 0; i < 6; i++)//(5)重复步骤2~4
	{
		CRC = CRC^data[i];//(2)数据与CRC异或
		for (int j = 0; j < 8; j++)//(4)重复8次步骤3
		{
			//(3)检测低位是否为1。方法:与1相与,低位为1则结果为1,低位为0则结果为0
			if (CRC & 1)//如果低位为1,则先右移一位,再与A001H相异或
			{
				CRC >>= 1;
				CRC ^= 0xA001;
			}
			else//低位为0,则右移一位
				CRC >>= 1;
		}
	}
	cout << CRC << endl;
	printf("%X", CRC);
	return 0;
}

之后,将该校验方法进行了封装:

#include
#include 
#include
using namespace std;

unsigned int modbusCRC16(const vector<unsigned char> &data)
{
	unsigned short CRC = 0xffff;//(1)CRC寄存器初值0xffff

	int dataSize = data.size();
	for (int i = 0; i < dataSize; i++)//(5)重复步骤2~4
	{
		CRC = CRC^data[i];//(2)数据与CRC异或
		for (int j = 0; j < 8; j++)//(4)重复8次步骤3
		{
			//(3)检测低位是否为1。方法:与1相与,低位为1则结果为1,低位为0则结果为0
			if (CRC & 1)//如果低位为1,则先右移一位,再与A001H相异或
			{
				CRC >>= 1;
				CRC ^= 0xA001;
			}
			else//低位为0,则右移一位
				CRC >>= 1;
		}
	}
	return CRC;
}
int main()
{
	vector<unsigned char> vec{ 0x01,0x02,0x02,0x03,0xFF };
	unsigned int CRC = modbusCRC16(vec);
	printf("%X", CRC);
	return 0;
}

2.测试

对上位机接收到的01 02 02 03 FF数据进行校验
在这里插入图片描述
结果如下:
在这里插入图片描述
这里,DI模块先发送低字节,再发送高字节,所以收到的是F9 08。windows下计算机为小端模式,低字节在前,可将08 F9转换为大端,再与F9 08进行比较。
关于小端转大端,Qt中可直接使用自带库函数qFromBigEndian(),需包含头文件#include
其他可参照C/C++ —— 小端转大端函数的使用

你可能感兴趣的:(Qt,Modbus,CRC16)