news 2026/4/18 12:57:28

Arduino与STM32的CRC16校验计算源码:支持Modbus协议与自定义功能的通用解决方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Arduino与STM32的CRC16校验计算源码:支持Modbus协议与自定义功能的通用解决方案

Arduino,stm32的crc16校验计算源码,支持crc16/modbus,自定义等功能。

撸代码的兄弟肯定都遇到过数据校验的问题,尤其是玩嵌入式开发的时候。今天咱们来聊聊CRC16校验在Arduino和STM32上的花式操作。别被那些复杂的数学公式吓到,直接上能跑的真代码。

先扔个查表法的实现镇场子:

const uint16_t crc16_table[] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, //...完整表太长,自己生成或找现成的 }; uint16_t crc16_calculate(uint8_t *data, uint16_t len) { uint16_t crc = 0xFFFF; while(len--) { crc = (crc >> 8) ^ crc16_table[(crc ^ *data++) & 0xFF]; } return crc; }

这段代码的精髓在查表加速。注意那个异或操作——初始值0xFFFF是Modbus的特色,要是玩别的协议记得改初始值。每次处理一个字节直接查表,比硬算快十倍不止。

想要支持Modbus协议?加点料:

uint16_t crc16_modbus(uint8_t *data, uint16_t len) { uint16_t crc = 0xFFFF; for(uint16_t i=0; i<len; i++){ crc ^= data[i]; for(int j=0; j<8; j++){ if(crc & 0x0001) { crc = (crc >> 1) ^ 0xA001; // 0x8005反转后的多项式 } else { crc >>= 1; } } } return crc; }

这里用了逐位计算的方式,注意多项式被反转了(Modbus标准操作)。那个0xA001其实是0x8005按位反转后的结果,别傻乎乎直接用标准多项式,会翻车。

玩STM32的兄弟可以试试硬件CRC外设:

uint16_t stm32_crc16(uint8_t *data, uint32_t len) { CRC->CR |= CRC_CR_RESET; // 复位寄存器 for(uint32_t i=0; i<len; i++){ *((__IO uint8_t *)&CRC->DR) = data[i]; // 字节写入 } return (CRC->DR & 0xFFFF) ^ 0xFFFF; // Modbus需要异或 }

F4系列实测能用,但注意硬件CRC的多项式可能和标准不同。这里最后那个异或0xFFFF就是用来适配Modbus的特殊处理,不用硬件加速的话可以删掉。

自定义参数才是真需求:

typedef struct { uint16_t poly; uint16_t init; bool refin; bool refout; uint16_t xorout; } CRC16_Config; uint16_t custom_crc16(uint8_t *data, uint16_t len, CRC16_Config cfg) { uint16_t crc = cfg.init; while(len--) { uint8_t c = *data++; if(cfg.refin) c = __RBIT(c) >> 24; // 位反转 crc ^= (c << 8); for(int i=0; i<8; i++){ crc = (crc & 0x8000) ? (crc << 1) ^ cfg.poly : (crc << 1); } } if(cfg.refout) crc = (crc << 8) | (crc >> 8); // 字节反转 return crc ^ cfg.xorout; }

这个模板够你玩转各种魔改CRC了。RBIT是STM32的指令级位反转,其他平台可以自己实现。注意多项式方向——左移还是右移决定了计算方向。

实测数据验证很重要:

void test() { uint8_t test_data[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02}; // Modbus CRC16应该返回0xC40B uint16_t crc = crc16_modbus(test_data, sizeof(test_data)); Serial.print("CRC16: 0x"); Serial.println(crc, HEX); }

跑这个测试用例,如果串口打印出C40B,恭喜你算法写对了。要是出问题,先检查字节顺序——Modbus是低位在前高位在后,别搞反了。

最后提醒:查表法在STM32上能起飞,但Arduino空间吃紧的话还是用逐位计算。遇到校验失败别慌,八成是多项式方向或初始值没设对。收藏这几个代码片段,够应付大多数嵌入式项目的校验需求了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 9:33:56

结构方程模型不会做?lavaan帮你5步搞定复杂路径分析

第一章&#xff1a;结构方程模型不会做&#xff1f;lavaan帮你5步搞定复杂路径分析结构方程模型&#xff08;SEM&#xff09;是社会科学、心理学和管理学中广泛使用的多变量统计方法&#xff0c;能够同时处理潜变量与观测变量之间的复杂关系。R语言中的lavaan包以其简洁的语法和…

作者头像 李华
网站建设 2026/4/18 9:33:57

R语言随机森林分类案例实战(工业级建模全流程曝光)

第一章&#xff1a;R语言随机森林分类案例实战&#xff08;工业级建模全流程曝光&#xff09;在工业数据科学项目中&#xff0c;构建可复现、高精度的分类模型是核心任务之一。随机森林因其对异常值鲁棒、无需复杂调参即可获得优异性能&#xff0c;广泛应用于故障检测、质量控制…

作者头像 李华
网站建设 2026/4/17 20:15:14

C/C++结构体超详细讲解

一、结构体核心概念&#xff08;C/C 通用&#xff09; 结构体&#xff08;struct&#xff09;是用户自定义的复合数据类型&#xff0c;核心作用是将不同类型的基础数据&#xff08;如int、char、指针等&#xff09;封装为一个整体&#xff0c;用来描述现实中 “具有多个属性的…

作者头像 李华
网站建设 2026/4/18 9:34:00

R语言时间序列预测实战(模型优化黄金法则)

第一章&#xff1a;R语言时间序列预测概述时间序列预测是数据分析中的核心任务之一&#xff0c;尤其在金融、经济、气象和销售等领域具有广泛应用。R语言凭借其强大的统计计算能力和丰富的扩展包&#xff08;如forecast、tseries和zoo&#xff09;&#xff0c;成为时间序列建模…

作者头像 李华
网站建设 2026/4/18 0:00:17

YOLOv8 WARNING警告信息解读大全

YOLOv8 WARNING警告信息解读大全 在深度学习项目中&#xff0c;模型“能跑”和“跑得稳”之间往往隔着一整套工程细节——而日志中的那些黄色提示&#xff0c;正是系统在悄悄提醒你&#xff1a;有些事&#xff0c;该优化了。 YOLOv8作为当前最主流的目标检测框架之一&#xff0…

作者头像 李华