【STM32】CRC 校验函数

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

c 复制代码
void crc_check(unsigned char *ptr,unsigned int len) //crc为开源函数
{
  unsigned long wcrc=0XFFFF;//预置16位crc寄存器,初值全部为1
  unsigned 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 为例,对详细代码进行解析:
c 复制代码
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

c 复制代码
uint16_t crc = 0xFFFF;
  1. 遍历整个数据区:

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

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

如果最低位是1,就右移并异或"生成多项式";

否则直接右移。

c 复制代码
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-8 0x07 0x00 0x00 SMBus
CRC-16 0x8005 0xFFFF 0x0000 Modbus
CRC-CCITT 0x1021 0xFFFF 0x0000 XMODEM
CRC-32 0x04C11DB7 0xFFFFFFFF 0xFFFFFFFF Ethernet, ZIP

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

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

相关推荐
不想学习!!13 分钟前
【STM32 基础复习 01】初识 STM32F103ZET6:型号、封装、引脚编号与特殊引脚
stm32·单片机·嵌入式硬件
wuyk55515 分钟前
66.嵌入式C语言进阶:共用体(Union)实战指南——单片机内存省一半的神级技巧
c语言·开发语言·stm32·单片机·嵌入式硬件
ACP广源盛139246256733 小时前
此芯 P1 AI BOX / AI NAS@ACP#IX8008、IX8024 应用场景与市场机会
大数据·人工智能·分布式·单片机·嵌入式硬件
广药门徒9 小时前
虚拟机联网20260725
嵌入式硬件
国产化创客10 小时前
Kindle 嵌入式交叉开发环境
嵌入式硬件·智能硬件
szxinmai主板定制专家12 小时前
RK3568+FPGA高速并行采集|半导体探针测试设备多通道同步数据采集系统设计
人工智能·嵌入式硬件·计算机视觉·fpga开发
Dlrb121114 小时前
ARM---I2C协议时序详解以及IMX6ULL使用I2C协议与AT24C02,LM75A芯片通信详解与示例代码
嵌入式硬件·arm·lm75a·i2c协议·at24c02·i2c时序
周洲083017 小时前
STM32独立/窗口看门狗完整配置|防止程序跑飞死机、异常复位
stm32·单片机·嵌入式硬件
论迹复利17 小时前
多平台移植 BTBLE Stack 的思路与踩坑实战——从 Ceva IP 到厂商适配层的迁移指南
嵌入式硬件·物联网·架构
SUNNYSPY00118 小时前
30N03DF-ASEMI扫地机器人主驱动30N03DF
单片机