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

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

相关推荐
sheepwjl1 天前
《嵌入式硬件(三):串口通信》
网络·嵌入式硬件·网络协议·串口通信
Geek 研究僧1 天前
大疆 Osmo 360:双 1 英寸 + 8K/50fps,改写全景相机市场格局
人工智能·数码相机·智能硬件·相机
嵌入式牛马在努力帮老板娶老婆1 天前
十四、STM32-----低功耗
stm32·单片机·嵌入式硬件
来生硬件工程师1 天前
【硬件笔记】负载是如何烧MOS的?
笔记·嵌入式硬件·硬件架构·硬件工程·硬件设计
少男的脸红藏不住心事1 天前
GD32入门到实战34--ARM启动流程
单片机·嵌入式硬件
zskj_zhyl1 天前
七彩喜智慧养老:科技向善,让“养老”变“享老”的智慧之选
大数据·人工智能·科技·物联网·机器人
日更嵌入式的打工仔1 天前
PHY的自适应协商简析
网络·嵌入式硬件·自适应·phy
铅笔侠_小龙虾1 天前
大话IOT(5) -- 七夕篇
物联网·蓝牙通信
CC呢1 天前
基于单片机坐姿提醒系统/久坐提醒设计
stm32·单片机·嵌入式硬件·单片机设计·久坐提醒
曙曙学编程1 天前
stm32——寄存器操作,蜂鸣器原理
c语言·c++·stm32·单片机·嵌入式硬件