CRC校验介绍

文章目录

CRC(Cyclic Redundancy Check,循环冗余校验)是一种根据数据产生简短固定位数校验码的算法,主要用于检测数字数据在传输或存储过程中是否发生错误。它的检错能力强、实现简单,在通信、存储等领域应用非常广泛。

核心原理:多项式除法

CRC校验的核心思想是:将二进制数据看作一个多项式的系数,然后使用一个预设的"除数"多项式(即生成多项式)去除这个数据多项式,得到的余数就是CRC校验码。

具体步骤

1、数据多项式:假设要发送的数据是 1011001(二进制)。可以把它表示为一个多项式:

bash 复制代码
M(x) = 1*x^6 + 0*x^5 + 1*x^4 + 1*x^3 + 0*x^2 + 0*x^1 + 1*x^0 = x^6 + x^4 + x^3 + 1

2、生成多项式:发送方和接收方必须事先约定一个生成多项式 G(x)。它的最高次幂记为 r(r位)。常见标准如:

bash 复制代码
CRC-8:x^8 + x^2 + x + 1 (对应二进制:1 0000 0111)

CRC-16-CCITT:x^16 + x^12 + x^5 + 1 (对应二进制:1 0001 0000 0010 0001)

CRC-32(以太网、ZIP等):x^32 + x^26 + x^23 + ... + x^2 + x + 1

3、补零并做模2除法:

在原数据比特串后面补 r 个0,得到 M(x) * x^r。这样做的目的是为余数(校验码)留出位置。

用这个补零后的数,除以生成多项式 G(x),除法使用 模2除法(即按位异或,不借位、不进位)。

4、得到CRC校验码:模2除法得到的余数(长度一定小于r位,如果不足r位则前面补0)就是CRC校验码。

5、发送数据:将原数据与计算出的CRC校验码拼接起来,形成最终的发送帧:原数据 + CRC码。

举例演示 (CRC-3)

原始数据:1101 (二进制)

生成多项式 G(x):1011 (对应 x^3 + x + 1, 最高次幂 r=3)

计算CRC码的步骤:

1、补3个0:数据后面加3个0 → 1101 000

2、模2除法:用 1101000 除以 1011(只做异或运算)

bash 复制代码
      1 0 0 1  (商,这里不关心)
    __________
1011 ) 1 1 0 1 0 0 0
      1 0 1 1
      -------
        1 1 0 0   (余数拖下一位0)
        1 0 1 1
        -------
          1 1 1 0 (余数拖下一位0)
          1 0 1 1
          -------
            1 0 1 0 (余数拖下一位0)
            1 0 1 1
            -------
              0 0 1   (最终余数)

3、得到余数:001。这就是CRC-3校验码(r=3位)。

4、发送数据:1101 + 001 = 1101001。

接收方校验:

接收方收到 1101001,使用同一个生成多项式 1011 去除它(同样做模2除法)。如果余数为 000,则说明数据在传输中没有出错;如果余数非0,则说明发生了错误。

bash 复制代码
      1 0 0 1
    __________
1011 ) 1 1 0 1 0 0 1
      1 0 1 1
      -------
        1 1 0 0
        1 0 1 1
        -------
          1 1 1 0
          1 0 1 1
          -------
            1 0 1 1
            1 0 1 1
            -------
              0 0 0 (余数为0,校验通过)

CRC的检错能力

CRC的检错能力与生成多项式的设计密切相关。一个设计良好的CRC多项式可以保证检测出:

所有奇数个错误(前提是多项式包含因子 (x+1))

所有双比特错误

所有长度 ≤ r 的突发错误(连续的一段错误)

长度 = r+1 的突发错误,漏检概率为 1/2^(r-1)

长度 > r+1 的突发错误,漏检概率为 1/2^r

硬件实现与软件计算

硬件实现:非常高效。可以使用带有反馈移位的线性反馈移位寄存器(LFSR) 来实现。每一位时钟周期处理一个输入位,结构极其简单。

做FPGA的伙伴可以学习,做软件的了解即可。博主也只是略微扫了一眼。

推荐文章:

详解线性反馈移位寄存器(LFSR)

CRC算法的硬件电路实现:串行电路和并行电路

软件实现:

1、直接计算法(慢):模拟上述除法过程,一位一位处理。

2、查表法(快):预先计算好所有256个字节的CRC值(因为一个字节有8位),然后对数据进行循环查表计算。这是目前最主流的软件CRC实现方式,速度很快。

推荐文章:

CRC校验C语言实现-CRC8、CRC16、CRC16的直接计算法、查表法

常见应用与标准

一些注意事项

1、不是纠错码:CRC主要用于检测错误,虽然理论上可以纠错,但在实践中通常只用于检测。发现错误后,一般会请求对方重传数据。

2、初值和异或值:许多实际标准会对CRC寄存器设置一个初始值(比如全1),并在计算结束后对结果异或一个固定值(如全1),以增强鲁棒性。这可以防止漏检数据开头的额外0。

3、输入/输出反转:有些协议(如以太网CRC-32)要求输入数据的每个字节比特顺序反转,或最终CRC值的字节顺序反转。这在实现时需要特别注意。

相关推荐
apcipot_rain1 小时前
计科八股20260606——二叉树、PCA、图深度学习、进程上下文、C语言预编译、文件读写、单精度浮点数
c语言·数据结构·算法·pca·图神经网络
189228048612 小时前
NV077固态MT29F16T08ESLCHL6-QAES:C
c语言·开发语言·性能优化
是阿建吖!11 小时前
【Linux】信号
android·linux·c语言·c++
三品吉他手会点灯12 小时前
C语言学习笔记 - 43.运算符与表达式 - 运算符1 - 运算符的分类和简单介绍
c语言·笔记·学习·算法
wuminyu14 小时前
Java锁机制之轻量级锁判断与尝试逻辑源码剖析
java·linux·c语言·jvm·c++
老H科研技术17 小时前
第 01 篇:MCP 概念与架构 —— AI 世界的“USB-C“
c语言·人工智能·chatgpt·架构·aigc·agi
社交怪人18 小时前
【判断奇偶】信息学奥赛一本通C语言解法(题号1041)
c语言
Jun62619 小时前
QT(1)-C/C++库生成和调用
c语言·开发语言·c++·qt
努力努力再努力wz20 小时前
【Qt入门系列】一文掌握 Qt 常用显示类控件:QLCDNumber、QProgressBar 与 QCalendarWidget
c语言·开发语言·数据结构·数据库·c++·git·qt