CRC校验原理及C语言实现指南
循环冗余校验(CRC)是确保数据传输完整性的核心技术,广泛应用于以太网、USB及嵌入式串口通信中。文章解析了WIDTH、POLY、INIT等关键参数模型,并通过手算实例与C语言标准库代码,展示从理论理解到工程落地的完整流程。
CRC校验的基础概念
在数据通信中,干扰可能导致比特翻转,造成接收端数据错误。为了保证可靠性,发送端会计算一组校验值附加在数据帧末尾,接收端通过同样的算法验证一致性。
常见的校验方法包括奇偶校验、校验和以及LRC/BCC。然而,简单的方法误码率较高。例如在奇校验中,若原始数据 0001 0011 含有3个“1”(奇数),校验位为0;传输中若发生干扰变为 0010 0011(仍为3个“1”,但第一位出错),奇校验依然通过,导致错误未被发现。
校验和也存在类似的隐蔽性错误风险:
相比之下,CRC基于除法余数原理,检错能力强且易于硬件实现,因此成为计算机领域最普遍的校验方式,如以太网使用的CRC-32配合曼彻斯特编码,极大提升了通信健壮性。
理解CRC参数模型
调用不同函数结果不一致的根源在于未对齐CRC的参数模型。一个标准的CRC配置需包含以下信息:
- NAME:模型名称(如CRC-8/MAXIM)。
- WIDTH:生成的CRC位宽(如8位、16位、32位)。
- POLY:生成多项式。通常省略最高位的1,转换为十六进制表示。例如多项式 $x^8 + x^2 + x + 1$,二进制为
1 0000 0111,省略首位后为0x07。 - INIT:初始值,位宽需与WIDTH一致,默认通常为
0x00。 - REFIN:输入数据是否按位反转。True表示在计算前对每个字节进行翻转。
- REFOUT:输出结果是否按位反转。True表示计算结束后对CRC值进行翻转。
- XOROUT:最终结果与多异或运算后的值。
不同协议对应不同的标准模型,常见应用包括:
- DS2401/18B20:使用CRC-8/MAXIM。
- SD/MMC卡:使用CRC-7/MMC。
- Modbus:使用CRC-16/MODBUS。
- STM32硬件模块:支持CRC-32模型。
多项式的选择涉及复杂的数学推导,工程中建议直接采用经过验证的标准模型以确保检错能力。
CRC计算原理与手算示例
掌握原理的关键在于执行模2除法。我们以CRC-8/MAXIM为例,计算原始数据 0x34 的校验值。
第1步:确认参数配置
CRC-8/MAXIM 的具体参数如下:
- POLY =
0x31(1 0011 0001) - INIT =
0x00 - XOROUT =
0x00 - REFIN = True
- REFOUT = True
第2步:预处理与移位
- 处理INIT:原始数据
0x34(0011 0100) 与 INIT00异或,结果不变。 - 数据翻转(REFIN):由于REFIN为True,将
0011 0100按位翻转得到0010 1100。 - 左移补零:原始数据向左移动WIDTH位(8位),低位补0。结果为
0010 1100 0000 0000。
第3步:模2除法求余数
使用模2除法(实质是无借位减法),将被除数除以多项式 1 0011 0001:
计算得到余数为低8位:1111 1011。
第4步:后处理与最终结果
- 异或(XOROUT):余数
1111 1011与 XOROUT0000 0000异或,结果仍为1111 1011。 - 输出翻转(REFOUT):由于REFOUT为True,将
1111 1011翻转得到1101 1111,即十六进制0xDF。
验证工具计算结果如下,确认手算正确:
数据校验机制
发送方将原始数据 0x34 拼接上CRC值 0xDF,组成数据帧 0x34DF。接收端通常有两种校验方式:
方式一:分离比对法
将接收到的帧分为数据和CRC两部分,在本地重新计算数据的CRC,并与接收到的CRC比对。一致则校验通过。
方式二:全帧整除法
将整个数据帧(含原数据和CRC部分)视为被除数,用相同的多项式进行模2除法。由于构造时已将余数拼入,理论上最终余数应为0。若余数不为0,则判定传输出错:
C语言代码实现
在实际开发中,建议使用成熟的开源库。这里以GitHub上的 crc-lib-c 为例,该库封装了常用的CRC算法。
第1步:引入头文件
在项目目录中包含库文件 crcLib.c 和 crcLib.h。
第2步:编写计算逻辑
以下代码演示如何计算长度为10字节的数组的CRC-8/MAXIM值:
#include <stdio.h>
#include <stdlib.h>
#include "crcLib.h"
int main()
{
uint8_t LENGTH = 10;
uint8_t data[LENGTH];
uint8_t crc;
// 初始化测试数据
for(int i = 0; i < LENGTH; i++)
{
data[i] = i * 5;
printf("%02x ", data[i]);
}
printf("\n");
// 调用MAXIM标准算法
crc = crc8_maxim(data, LENGTH);
printf("CRC-8/MAXIM:%02x\n", crc);
return 0;
}
第3步:运行验证
编译运行后,控制台输出的CRC结果如下:
辅助工具推荐
在进行底层驱动开发(如Verilog或裸机C代码)时,可利用在线工具作为标准答案进行对照验证:
- 在线计算:www.ip33.com/crc.html
- 离线工具:CRC_Calc v0.1.exe、GCRC.exe
- 格西CRC计算器界面直观,适合快速排查模型参数:
CRC虽不能保证100%捕获所有错误,但在合理位数和多项式下能覆盖绝大多数传输损伤。实际应用中务必严格遵循协议规定的标准参数模型。
以上就是CRC校验原理及其C语言实现详解的详细内容,更多关于C语言 CRC校验的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













