CRC-16 MODBUS原理,附实测可用源码

简介: 之前做串口解析,CRC校验一直用和校验,就是吧各个位加在一起,新来一个串口协议,是CRC-16 MODBUS的形式校验,不会呀,从网上找了找资源,没有找到源码,都要下载,分享出来。

CRC-16 MODBUS原理+源码

之前做串口解析,CRC校验一直用和校验,就是吧各个位加在一起,新来一个串口协议,是CRC-16 MODBUS的形式校验,不会呀,从网上找了找资源,没有找到源码,都要下载,分享出来。

先介绍下原理

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

    1.预置1个16位的寄存器为十六进制FFFF(即全为1);称此寄存器为CRC寄存器;
    2.把第一个8位二进制数据 (既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器;
    3.把CRC寄存器的内容右移一 位(朝低位)用0填补最高位,并检查右移后的移出位;
    4.如果移出位为0:重复第3步(再次右移一位);
    如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;(Modbus)
    5.重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;
    6.重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;
    7.将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低字节进行交换;
    8.最后得到的CRC寄存器内容即为:CRC码。

源码

如果只是想单纯的用,就只把下面代码贴上进行计算CRC就行了

unsigned int GetCRC16(unsigned char *ptr,  unsigned char len)
{
    unsigned int index;
    unsigned char crch = 0xFF;  //高CRC字节
    unsigned char crcl = 0xFF;  //低CRC字节
    unsigned char code TabH[] = {  //CRC高位字节值表
        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  
    } ;  
    unsigned char code TabL[] = {  //CRC低位字节值表
        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  
    } ;
    while (len--)  //计算指定长度的CRC
    {
        index = crch ^ *ptr++;
        crch = crcl ^ TabH[ index];
        crcl = TabL[ index];
    }
   
    return ((crch<<8) | crcl);  
}                           

该函数即直接返回计算的CRC值

校验软件

测试自己写的代码计算的CRC对不对可以使用如下软件
在这里插入图片描述
a4 01 07 06 20 f1 计算的 CRC-16 MODBUS 的值即为CE1D。
软件下载地址:
链接: https://pan.baidu.com/s/1sVCNNXbgVJcmesVt-2XGQw 提取码: j9aq

相关文章
|
C++
C/C++给文件加crc校验
C/C++给文件加crc校验
532 1
|
Linux 异构计算 Windows
Windows操作系统:指定网卡ping连通性
某些时候,板卡上留有两个及以上万兆网口,在没有其他FPGA板卡或者只是想测一下网口或者万兆光模块的通路时,可以通过回环互ping来验证下连通性
5296 0
|
10月前
|
算法 编译器 C语言
【2026最新】MinGW64官网下载安装保姆级教程(附安装包+图文并茂)
MinGW-w64 是 Windows 下的轻量级 GNU 编译器集合,支持 C/C++ 编译,无需虚拟机即可生成独立 exe 文件。它体积小、免安装、静态链接运行库,兼容 Win10/11 与旧系统,配置简单,广泛用于算法开发、刷题及教学场景。
16703 5
|
7月前
|
监控 测试技术 C#
基于C# WinForm实现的串口调试助手源码
基于C# WinForm实现的串口调试助手源码,包含串口配置、数据收发、HEX/ASCII转换、CRC校验等核心功能,支持实时流量统计和日志记录
|
11月前
|
NoSQL 算法 Linux
OpenOCD下载安装保姆级教程(附安装包,非常详细)
OpenOCD是一款开源片上调试工具,支持JTAG/SWD接口,提供GDB Server、TCL脚本自动化等功能,可实现断点调试、Flash烧录、FPGA编程等,广泛应用于嵌入式开发与量产测试,被誉为“穷人的Lauterbach”。跨平台且免费,配置灵活但稍复杂,是嵌入式工程师的高效调试利器。
|
缓存 弹性计算 运维
网络管理利器:掌握常用的CMD命令
本文介绍了常用的网络CMD命令及其用法,包括`ping`、`ipconfig`、`tracert`、`nslookup`、`netstat`、`route`、`telnet`、`ftp`、`netsh`、`arp`、`nbtstat`、`hostname`、`systeminfo`、`ipconfig /flushdns`和`tasklist`。这些命令在日常的网络管理和故障排查中非常实用,帮助你轻松进行网络诊断、配置和监控。
2553 1
|
机器人 测试技术 C++
ModbusCRC16校验 示例代码
本文提供了ModbusCRC16校验的示例代码,包括计算CRC、添加CRC校验位、删除CRC校验位和比较CRC校验位等四种常用函数的实现,以及一个完整的示例代码。这些代码在Ubuntu20.04环境下经过测试并确认有效。示例代码采用C++编写,展示了如何使用这些函数来处理Modbus通信中的数据校验。
1756 2
|
消息中间件 Kafka 数据库
微服务架构中,如何确保服务之间的数据一致性
微服务架构中,如何确保服务之间的数据一致性