当前位置: 首页 > news >正文

【STM32】CRC 校验函数

先上一下 CRC校验 的源代码:

void crc_check(unsigned char *ptr,unsigned int len) //crc为开源函数
{unsigned long wcrc=0XFFFF;//预置16位crc寄存器,初值全部为1unsigned char temp;//定义中间变量int i=0,j=0;//定义计数for(i=0;i<len;i++)//循环计算每个数据{temp=*ptr&0X00FF;//将八位数据与crc寄存器亦或ptr++;//指针地址增加,指向下个数据wcrc^=temp;//将数据存入crc寄存器for(j=0;j<8;j++)//循环计算数据的{if(wcrc&0X0001)//判断右移出的是不是1,如果是1则与多项式进行异或。{wcrc>>=1;//先将数据右移一位wcrc^=0XA001;//与上面的多项式进行异或}else//如果不是1,则直接移出{wcrc>>=1;//直接移出}}}temp=wcrc;//crc的值L_CRC=wcrc;//crc的低八位H_CRC=wcrc>>8;//crc的高八位
}

这个函数通常用于执行 CRC 校验,即对输入的数据指针 ptr 和长度 len 进行 循环冗余校验(Cyclic Redundancy Check)。CRC 是一种非常常见且高效的数据完整性校验算法,广泛应用于:

  • 通信协议(如 Modbus、CAN、USB)
  • 存储设备(校验文件完整性)
  • 嵌入式系统(数据包校验)

CRC 校验概念

CRC 校验的作用:检测数据在传输或保存过程中是否被篡改或损坏
原理:将数据看作一个二进制多项式,除以一个“生成多项式”,取余数作为CRC校验码


常见类型:
CRC8
CRC16(如 Modbus)
CRC32(如以太网、ZIP)

我们这里以标准的 Modbus CRC16 为例,对详细代码进行解析:
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];  // 将每个字节与 CRC 当前值异或for (uint8_t j = 0; j < 8; j++) {if (crc & 0x0001) {crc >>= 1;crc ^= 0xA001;  // 多项式:0x8005 反转为 0xA001} else {crc >>= 1;}}}return crc;
}
逐步解析:
  1. 初始化 CRC:

Modbus协议规定初始值为 0xFFFF

uint16_t crc = 0xFFFF;
  1. 遍历整个数据区:

每个字节与当前 CRC 值低字节异或:

for (i = 0; i < len; i++) {crc ^= data[i];...
}
  1. 对每个字节进行 8 次移位处理:

如果最低位是1,就右移并异或“生成多项式”;
否则直接右移。

for (j = 0; j < 8; j++) {if (crc & 0x0001) {crc >>= 1;crc ^= 0xA001;} else {crc >>= 1;}
}

需要注意的是:

CRC 校验是 无错误纠正能力 的,只能检测错误
必须和接收端使用相同的 CRC 算法、多项式、初始值
对于不同协议(如 Modbus、CAN),CRC 实现略有不同,例如,本文最初提供的便是 Modbus 协议的 CRC校验。

CRC 的多项式
CRC类型多项式初始值结果异或应用
CRC-80x070x000x00SMBus
CRC-160x80050xFFFF0x0000Modbus
CRC-CCITT0x10210xFFFF0x0000XMODEM
CRC-320x04C11DB70xFFFFFFFF0xFFFFFFFFEthernet, ZIP

简单来说,函数 crc_check(unsigned char *ptr, unsigned int len) 是用来对指定内存块执行 CRC 校验的工具函数, 常用于嵌入式通信中验证数据完整性。

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!

http://www.lryc.cn/news/596432.html

相关文章:

  • linux初识网络及UDP简单程序
  • 二、计算机网络技术——第3章:数据链路层
  • 基于卷积神经网络与小波变换的医学图像超分辨率算法复现
  • DeepSPV:一种从2D超声图像中估算3D脾脏体积的深度学习流程|文献速递-医学影像算法文献分享
  • zmaiFy来说软字幕和硬字幕有什么优缺点?
  • qtbase5-dev库使用介绍
  • 生成式人工智能对网络安全的影响
  • OpenCV快速入门之CV宝典
  • 博物馆智慧导览系统AR交互与自动感应技术:从虚实融合到智能讲解的技术实践
  • 内核协议栈源码阅读(一) ---驱动与内核交互
  • Spring AI Alibaba + JManus:从架构原理到生产落地的全栈实践——一篇面向 Java 架构师的 20 分钟深度阅读
  • 打造智能化应用新思路:扣子Coze工作流详解与最佳实践
  • MCU中的总线桥是什么?
  • js的基本内容:引用、变量、打印、交互、定时器、demo操作
  • 聚簇索引的优势
  • LeetCode|Day22|231. 2 的幂|Python刷题笔记
  • windows下nvm的安装及使用
  • 融云“通信+AI”解决方案三大场景实例
  • 使用mybatis实现模糊查询和精准查询切换的功能
  • GraphRAG的部署和生成检索过程体验
  • 小白成长之路-部署Zabbix7
  • 使用react编写一个简单的井字棋游戏
  • 17.VRRP技术
  • 接口自动化测试种涉及到接口依赖怎么办?
  • 微调大语言模型(LLM)有多难?
  • Google Gemini 体验
  • 深入解析Hadoop中的推测执行:原理、算法与策略
  • kafka查看消息的具体内容 kafka-dump-log.sh
  • SDC命令详解:使用set_min_library命令进行约束
  • Unity笔记——事件中心