【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 校验的工具函数, 常用于嵌入式通信中验证数据完整性。

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

相关推荐
ksk自在无敌1 小时前
ESP8266的AP模式与STA编写,
stm32·单片机·嵌入式硬件
晶振厂家-晶发电子2 小时前
怎么判断晶振的好坏,有什么简单的办法
单片机·嵌入式硬件
jllllyuz2 小时前
SysTick定时器的工作原理是什么
stm32·单片机·嵌入式硬件
RIKI_12 小时前
【浅学】tflite-micro + ESP32S3 + VScode + ESP-IDF 基于例程快速实现自己的图像分类模型训练部署全流程
单片机·分类
程序猫A建仔3 小时前
【物联网】基于树莓派的物联网开发【26】——树莓派开启串口并配置串口助手Minicom
物联网
滴滴滴嘟嘟嘟.3 小时前
STM32 HAL驱动MPU6050传感器
stm32·单片机·嵌入式硬件
食鹿...5 小时前
【记录贴】STM32 I2C 控制 OLED 卡死?根源在 SR1 与 SR2 的读取操作
stm32·单片机·嵌入式硬件
k↑6 小时前
物联网之小白调试网关设备
网络·物联网
范纹杉想快点毕业6 小时前
《嵌入式 C 语言编码规范与工程实践个人笔记》参考华为C语言规范标准
服务器·c语言·stm32·单片机·华为·fpga开发·51单片机
Chipi Chipi6 小时前
STM32即插即用HAL库驱动系列——4位串行数码管显示
stm32·单片机·嵌入式硬件