文章目录
- 2.5 CRC 校验
- 2.5.1 前言
- 2.5.2 CRC算法简介
- 2.5.3 CRC计算的详细过程
- 2.5.4 CRC校验的两种方法详解
- **分离比较法**
- **整体运算法**
- **不同位出错与余数的关系**
- **总结**
- 2.5.5 CRC计算的C++实现及工具介绍
- **C++实现CRC计算**
- **CRC计算工具推荐**
- **2.5.6 总结:CRC校验的局限性与纠错原理**
本博客为系列博客,主要讲解各基带算法的原理与应用,包括:viterbi解码、Turbo编解码、Polar编解码、CORDIC算法、CRC校验、FFT/DFT、QAMtiaozhi/解调、QPSK调制/解调。其他博客链接如下:
- 探秘基带算法:从原理到5G时代的通信变革【一】引言
- 探秘基带算法:从原理到5G时代的通信变革【二】Viterbi解码
- 探秘基带算法:从原理到5G时代的通信变革【三】Turbo 编解码
- 探秘基带算法:从原理到5G时代的通信变革【四】Polar 编解码(一)
- 探秘基带算法:从原理到5G时代的通信变革【四】Polar 编解码(二)
- 探秘基带算法:从原理到5G时代的通信变革【五】CORDIC算法
- 探秘基带算法:从原理到5G时代的通信变革【六】CRC 校验
- 探秘基带算法:从原理到5G时代的通信变革【七】FFT/DFT
- 探秘基带算法:从原理到5G时代的通信变革【八】QAM 调制 / 解调
- 探秘基带算法:从原理到5G时代的通信变革【九】QPSK调制/解调
- 探秘基带算法:从原理到5G时代的通信变革【十】基带算法应用与对比
2.5 CRC 校验
[CRC校验]手算与直观演示_哔哩哔哩_bilibili,讲解的非常清楚。一定要先看这个!!!
2.5.1 前言
在现代通信系统中,数据传输的完整性是确保信息正确传递的关键。一个完整的数据帧通常由多个部分构成,包括帧头、数据位和帧尾等。其中,校验位的作用尤为重要,它通过对原始数据进行特定算法计算生成一个校验值,并将其附加到数据帧中。接收方接收到数据后,使用相同的算法对原始数据重新计算校验值并与接收到的校验值进行比较。如果两者一致,则说明数据在传输过程中未发生错误;否则,表明数据可能被篡改或损坏,需要丢弃并请求重发。
常见的校验算法包括奇偶校验、校验和、循环冗余校验(Cyclic Redundancy Check,CRC),以及较少使用的纵向冗余校验(Longitudinal Redundancy Check,LRC)和块校验码(Block Check Character,BCC)。然而,不同的校验方法具有各自的优缺点。例如,奇偶校验是一种简单但误码率较高的校验方式。以串口通信中的奇校验为例,假设原始数据为0001 0011
,其中1
的个数为3,因此奇校验位为0
。如果传输过程中数据受到干扰,接收端接收到的数据变为0010 0011
,尽管1
的个数仍为奇数,校验通过,但实际上数据已经发生了错误。类似的问题也可能出现在校验和算法中。
为了提高数据传输的健壮性和稳定性,通信系统通常结合高效的校验算法和数字信号编码方式。例如,以太网协议采用了CRC-32校验和曼彻斯特编码。这种组合能够显著降低误码率,确保数据的可靠传输。本文将重点介绍CRC校验的原理及其具体实现方法。
2.5.2 CRC算法简介
循环冗余校验(Cyclic Redundancy Check,CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。
CRC校验计算速度快,检错能力强,易于用编码器等硬件电路实现。从检错的正确率与速度、成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC 成为计算机信息通信领域最为普遍的校验方式。常见应用有以太网/USB通信,压缩解压,视频编码,图像存储,磁盘读写等。
- CRC参数模型
不知道你是否遇到过这种情况,同样的CRC多项式,调用不同的CRC计算函数,得到的结果却不一样,而且和手算的结果也不一样,这就涉及到CRC的参数模型了。计算一个正确的CRC值,需要知道CRC的参数模型。
一个完整的CRC参数模型应该包含以下信息:
- NAME:参数模型名称。
- WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位。
- POLY:十六进制多项式,省略最高位1,如
x
8
+
x
2
+
x
+
1
x^8 + x^2 + x + 1
x8+x2+x+1,二进制为
1 0000 0111
,省略最高位1,转换为十六进制为0x07
。 - INIT:CRC初始值,和WIDTH位宽一致。
- REFIN:true或false,在进行计算之前,原始数据是否翻转,如原始数据:
0x34 = 0011 0100
,如果REFIN为true,进行翻转之后为0010 1100 = 0x2c
。 - REFOUT:true或false,运算完成之后,得到的CRC值是否进行翻转,如计算得到的CRC值:
0x97 = 1001 0111
,如果REFOUT为true,进行翻转之后为11101001 = 0xE9
。 - XOROUT:计算结果与此参数进行异或运算后得到最终的CRC值,和WIDTH位宽一致。
通常如果只给了一个多项式,其他的没有说明则:INIT=0x00,REFIN=false,REFOUT=false,XOROUT=0x00。
- 常用的21个标准CRC参数模型
以下是常用的21个标准CRC参数模型:
CRC算法名称 | 多项式公式 | WIDTH | POLY | INIT | XOROUT | REFIN | REFOUT |
---|---|---|---|---|---|---|---|
CRC-4/ITU | x 4 + x + 1 x^4 + x + 1 x4+x+1 | 4 | 03 | 00 | 00 | TRUE | TRUE |
CRC-5/EPC | x 5 + x 3 + 1 x^5 + x^3 + 1 x5+x3+1 | 5 | 09 | 09 | 00 | FALSE | FALSE |
CRC-5/ITU | x 5 + x 4 + x 2 + 1 x^5 + x^4 + x^2 + 1 x5+x4+x2+1 | 5 | 15 | 00 | 00 | TRUE | TRUE |
CRC-5/USB | x 5 + x 2 + 1 x^5 + x^2 + 1 x5+x2+1 | 5 | 05 | 1F | 1F | TRUE | TRUE |
CRC-6/ITU | x 6 + x + 1 x^6 + x + 1 x6+x+1 | 6 | 03 | 00 | 00 | TRUE | TRUE |
CRC-7/MMC | x 7 + x 3 + 1 x^7 + x^3 + 1 x7+x3+1 | 7 | 09 | 00 | 00 | FALSE | FALSE |
CRC-8 | x 8 + x 2 + x + 1 x^8 + x^2 + x + 1 x8+x2+x+1 | 8 | 07 | 00 | 00 | FALSE | FALSE |
CRC-8/ITU | x 8 + x 2 + x + 1 x^8 + x^2 + x + 1 x8+x2+x+1 | 8 | 07 | 00 | 55 | FALSE | FALSE |
CRC-8/ROHC | x 8 + x 2 + x + 1 x^8 + x^2 + x + 1 x8+x2+x+1 | 8 | 07 | FF | 00 | TRUE | TRUE |
CRC-8/MAXIM | x 8 + x 5 + x 4 + 1 x^8 + x^5 + x^4 + 1 x8+x5+x4+1 | 8 | 31 | 00 | 00 | TRUE | TRUE |
CRC-16/IBM | x 16 + x 15 + x 2 + 1 x^{16} + x^{15} + x^2 + 1 x16+x15+x2+1 | 16 | 8005 | 0000 | 0000 | TRUE | TRUE |
CRC-16/MAXIM | x 16 + x 15 + x 2 + 1 x^{16} + x^{15} + x^2 + 1 x16+x15+x2+1 | 16 | 8005 | 0000 | FFFF | TRUE | TRUE |
CRC-16/USB | x 16 + x 15 + x 2 + 1 x^{16} + x^{15} + x^2 + 1 x16+x15+x2+1 | 16 | 8005 | FFFF | FFFF | TRUE | TRUE |
CRC-16/MODBUS | x 16 + x 15 + x 2 + 1 x^{16} + x^{15} + x^2 + 1 x16+x15+x2+1 | 16 | 8005 | FFFF | 0000 | FALSE | FALSE |
CRC-16/CCITT | x 16 + x 12 + x 5 + 1 x^{16} + x^{12} + x^5 + 1 x16+x12+x5+1 | 16 | 1021 | 0000 | 0000 | TRUE | TRUE |
CRC-16/CCITT-FALSE | x 16 + x 12 + x 5 + 1 x^{16} + x^{12} + x^5 + 1 x16+x12+x5+1 | 16 | 1021 | FFFF | 0000 | FALSE | FALSE |
CRC-16/X25 | x 16 + x 12 + x 5 + 1 x^{16} + x^{12} + x^5 + 1 x16+x12+x5+1 | 16 | 1021 | FFFF | FFFF | TRUE | TRUE |
CRC-16/XMODEM | x 16 + x 12 + x 5 + 1 x^{16} + x^{12} + x^5 + 1 x16+x12+x5+1 | 16 | 1021 | 0000 | 0000 | FALSE | FALSE |
CRC-16/DNP | x 16 + x 13 + x 12 + x 11 + x 10 + x 8 + x 6 + x 5 + x 2 + 1 x^{16} + x^{13} + x^{12} + x^{11} + x^{10} + x^8 + x^6 + x^5 + x^2 + 1 x16+x13+x12+x11+x10+x8+x6+x5+x2+1 | 16 | 3D65 | 0000 | FFFF | TRUE | TRUE |
CRC-32 | x 32 + x 26 + x 23 + x 22 + x 16 + x 12 + x 11 + x 10 + x 8 + x 7 + x 5 + x 4 + x 2 + x + 1 x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 | 32 | 04C11DB7 | FFFFFFFF | FFFFFFFF | TRUE | TRUE |
CRC-32/MPEG-2 | x 32 + x 26 + x 23 + x 22 + x 16 + x 12 + x 11 + x 10 + x 8 + x 7 + x 5 + x 4 + x 2 + x + 1 x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 | 32 | 04C11DB7 | FFFFFFFF | 0 | FALSE | FALSE |
这些参数模型定义了不同应用场景下的CRC校验方法,确保了在特定协议或标准下数据传输的可靠性和一致性。
- CRC校验在电子通信中的广泛应用
循环冗余校验(Cyclic Redundancy Check,CRC)是一种广泛应用于电子通信领域的数据完整性检测技术。其高效性和可靠性使其成为现代通信系统中不可或缺的一部分。无论是芯片级的单总线通信,还是大规模的数据传输协议,CRC校验都扮演着重要角色。
美信(MAXIM)芯片中的CRC-8/MAXIM模型
美信公司(MAXIM)生产的DS2401和DS18B20等芯片广泛使用了CRC-8/MAXIM
参数模型。这种模型特别适用于单总线通信协议,能够有效检测数据传输过程中的错误。CRC-8/MAXIM
的核心参数包括:
- 多项式:
x
8
+
x
5
+
x
4
+
1
x^8 + x^5 + x^4 + 1
x8+x5+x4+1,十六进制表示为
0x31
。 - 初始值:
0x00
。 - 输入翻转(REFIN):TRUE,表示在计算前需要对输入数据进行比特级翻转。
- 输出翻转(REFOUT):TRUE,表示计算结果需要再次翻转。
- 异或值(XOROUT):
0x00
。
通过这些参数的组合,CRC-8/MAXIM
能够在有限的计算资源下提供高效的错误检测能力。
SD卡或MMC中的CRC-7/MMC模型
SD卡和MMC存储设备中使用的CRC-7/MMC
模型是一种低开销、高性能的校验方法。它主要用于检测命令和数据传输过程中的错误。CRC-7/MMC
的核心参数如下:
- 多项式:
x
7
+
x
3
+
1
x^7 + x^3 + 1
x7+x3+1,十六进制表示为
0x09
。 - 初始值:
0x00
。 - 输入翻转(REFIN):FALSE。
- 输出翻转(REFOUT):FALSE。
- 异或值(XOROUT):
0x00
。
由于SD卡和MMC设备通常涉及大量数据块的传输,CRC-7/MMC
模型以其简洁性和高效性成为理想选择。
Modbus通信中的CRC-16/MODBUS模型
Modbus是一种常见的工业通信协议,广泛应用于自动化控制领域。在Modbus通信中,CRC-16/MODBUS
模型用于确保数据帧的完整性。其核心参数包括:
- 多项式:
x
16
+
x
15
+
x
2
+
1
x^{16} + x^{15} + x^2 + 1
x16+x15+x2+1,十六进制表示为
0x8005
。 - 初始值:
0xFFFF
。 - 输入翻转(REFIN):FALSE。
- 输出翻转(REFOUT):FALSE。
- 异或值(XOROUT):
0x0000
。
CRC-16/MODBUS
模型通过较高的位宽提供了更强的错误检测能力,适合工业环境中复杂数据帧的校验需求。
USB协议中的CRC-5/USB和CRC-16/USB模型
USB(Universal Serial Bus)协议中使用了两种不同的CRC模型来满足不同场景的需求:
-
CRC-5/USB:用于短数据包的快速校验,常见于握手信号和令牌包。
- 多项式:
x
5
+
x
2
+
1
x^5 + x^2 + 1
x5+x2+1,十六进制表示为
0x05
。 - 初始值:
0x1F
。 - 输入翻转(REFIN):TRUE。
- 输出翻转(REFOUT):TRUE。
- 异或值(XOROUT):
0x1F
。
- 多项式:
x
5
+
x
2
+
1
x^5 + x^2 + 1
x5+x2+1,十六进制表示为
-
CRC-16/USB:用于数据包的完整校验,适合大规模数据传输。
- 多项式:
x
16
+
x
15
+
x
2
+
1
x^{16} + x^{15} + x^2 + 1
x16+x15+x2+1,十六进制表示为
0x8005
。 - 初始值:
0xFFFF
。 - 输入翻转(REFIN):TRUE。
- 输出翻转(REFOUT):TRUE。
- 异或值(XOROUT):
0xFFFF
。
- 多项式:
x
16
+
x
15
+
x
2
+
1
x^{16} + x^{15} + x^2 + 1
x16+x15+x2+1,十六进制表示为
这两种模型的结合使得USB协议能够在保证速度的同时兼顾可靠性。
图:USB协议中CRC校验的应用。
STM32硬件CRC计算模块中的CRC-32模型
STM32微控制器内置了硬件CRC计算模块,支持CRC-32
标准模型。该模型广泛应用于文件传输和网络通信中,具有极高的错误检测能力。其核心参数如下:
- 多项式:
x
32
+
x
26
+
x
23
+
x
22
+
x
16
+
x
12
+
x
11
+
x
10
+
x
8
+
x
7
+
x
5
+
x
4
+
x
2
+
x
+
1
x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1,十六进制表示为
0x04C11DB7
。 - 初始值:
0xFFFFFFFF
。 - 输入翻转(REFIN):TRUE。
- 输出翻转(REFOUT):TRUE。
- 异或值(XOROUT):
0xFFFFFFFF
。
通过硬件加速,STM32能够在不占用过多CPU资源的情况下完成复杂的CRC计算,显著提高了系统的性能。
图:STM32硬件CRC模块的工作原理。
2.5.3 CRC计算的详细过程
在电子通信领域,CRC校验是一种广泛使用的数据完整性检测技术。为了更好地理解CRC校验的工作原理,我们可以通过一个具体的例子来手算CRC值,并逐步解析其计算过程。
- 问题描述
假设原始数据为0x34
,使用CRC-8/MAXIM
参数模型计算CRC值。根据CRC-8/MAXIM
的参数模型,我们可以提取以下信息:
- POLY =
0x31
=0011 0001
(最高位1
已省略) - INIT =
0x00
- XOROUT =
0x00
- REFIN =
TRUE
(输入数据需要翻转) - REFOUT =
TRUE
(输出结果需要翻转)
有了这些参数,我们就可以开始详细的计算过程。
- 计算步骤
(1)第一步:初始化
原始数据为0x34
,对应的二进制表示为0011 0100
。初始值INIT
为0x00
,因此原始数据与初始值进行异或运算后保持不变:
原始数据 ⊕ INIT = 0011 0100 ⊕ 0000 0000 = 0011 0100 \text{原始数据} \oplus \text{INIT} = 0011\ 0100 \oplus 0000\ 0000 = 0011\ 0100 原始数据⊕INIT=0011 0100⊕0000 0000=0011 0100
(2)第二步:输入数据翻转
由于REFIN = TRUE
,我们需要对原始数据进行比特级翻转。翻转后的结果为:
0011 0100 → 0010 1100 0011\ 0100 \rightarrow 0010\ 1100 0011 0100→0010 1100
(3)第三步:左移并补零
将翻转后的数据左移8位,并在末尾补上8个0
,得到扩展后的数据:
0010 1100 0000 0000 0010\ 1100\ 0000\ 0000 0010 1100 0000 0000
(4)第四步:模2除法求余数
接下来,使用生成多项式POLY = 0x31 = 1 0011 0001
对扩展后的数据进行模2除法运算。模2除法的核心是通过逐位比较和异或操作,逐步消去最高位的1
,直到余数的长度小于多项式的阶数为止。
以下是具体的计算过程:
-
取扩展数据的前9位(因为生成多项式的阶数为8):
1011 0000 0000
。 -
将生成多项式
1 0011 0001
与这9位进行异或运算:
1011 0000 0 ⊕ 1 0011 0001 = 0010 1000 1 1011\ 0000\ 0 \oplus 1\ 0011\ 0001 = 0010\ 1000\ 1 1011 0000 0⊕1 0011 0001=0010 1000 1 -
将结果右移,继续取下一位数据进行异或运算,重复上述步骤,直到处理完整个扩展数据。
-
最终得到的余数为
1111 1011
。 -
如果这个计算过程不理解,请查看:[CRC校验]手算与直观演示_哔哩哔哩_bilibili,讲解的非常清楚。一定要看!!!
(5)第五步:输出结果翻转
由于REFOUT = TRUE
,需要对最终结果进行比特级翻转。翻转后的结果为:
1111 1011 → 1101 1111 1111\ 1011 \rightarrow 1101\ 1111 1111 1011→1101 1111
(6)第六步:与XOROUT进行异或
将模2除法得到的余数1111 1011
与XOROUT
值0x00
进行异或运算:
1101 1111 ⊕ 0000 0000 = 1101 1111 = 0 x D F 1101\ 1111 \oplus 0000\ 0000 = 1101\ 1111 = 0xDF 1101 1111⊕0000 0000=1101 1111=0xDF
(7)最终结果
经过以上步骤,我们得到了CRC-8/MAXIM
校验值为0xDF
。将该值附加到原始数据之后,完整的数据帧为:
0011 0100 1101 1111 = 34 D F 0011\ 0100\ 1101\ 1111 = 34DF 0011 0100 1101 1111=34DF
- 验证计算结果
为了确保计算正确性,可以使用CRC计算工具或软件进行验证。如果计算结果与工具输出一致,则说明我们的计算过程无误。需要注意的是,不同工具可能使用不同的参数模型,因此在验证时必须确保所有参数(如INIT
、XOROUT
、REFIN
、REFOUT
等)完全一致。
- 总结
通过上述手算过程,我们详细解析了CRC-8/MAXIM
校验值的计算方法。这一过程包括以下几个关键步骤:
- 初始化数据并与初始值进行异或运算。
- 根据
REFIN
参数决定是否对输入数据进行翻转。 - 对扩展后的数据进行模2除法运算,求得余数。
- 根据
REFOUT
参数决定是否对余数进行翻转,得到初步结果。 - 根据
XOROUT
参数对初步结果进行异或运算,得到最终结果。
CRC校验的精确性和可靠性依赖于正确的参数设置。因此,在实际应用中,务必仔细核对所有参数,以确保计算结果的一致性。
2.5.4 CRC校验的两种方法详解
在电子通信中,CRC(循环冗余校验)不仅用于数据传输前的错误检测码生成,还用于接收端的数据校验。接收端可以通过两种方式来验证接收到的数据帧是否正确:分离比较法和整体运算法。以下将详细介绍这两种方法的工作原理及其背后的数学逻辑。
分离比较法
方法概述
分离比较法的核心思想是对接收到的数据帧进行分离处理,将原始数据与附加的CRC校验码分开。然后,仅对原始数据重新计算CRC值,并将其与接收到的CRC校验码进行比较。如果两者一致,则说明数据传输无误;否则,数据可能在传输过程中发生了错误。
具体步骤
-
数据分离
假设接收到的数据帧为0011 0100 1101 1111
,前8位0011 0100
是原始数据,后8位1101 1111
是CRC校验码。 -
重新计算CRC值
使用与发送端相同的CRC参数模型(如多项式、初始值、输入输出翻转等),对分离出的原始数据0011 0100
重新计算CRC值。 -
比较结果
将重新计算得到的CRC值与接收到的CRC校验码1101 1111
进行比较。如果两者相等,则认为数据传输正确;否则,数据可能存在错误。
整体运算法
方法概述
整体运算法的核心思想是直接对整个接收到的数据帧进行CRC计算。由于数据帧是由原始数据左移 n n n位并附加CRC值构成的,因此如果数据帧没有发生错误,直接对其进行CRC计算的结果应该为0。
通俗解释与举例说明
为了更好地理解“数据帧是由原始数据左移 n n n位并附加CRC值构成的,因此如果数据帧没有发生错误,直接对其进行CRC计算的结果应该为0”这句话,我们可以从一个简单的例子出发,并结合CRC校验的基本原理进行说明。
背景知识回顾
CRC计算的核心思想
CRC校验本质上是一种基于模2除法的算法。发送端通过将原始数据左移 n n n位(其中 n n n是CRC值的位数),然后用生成多项式 P P P对扩展后的数据进行模2除法运算,得到余数作为CRC值。最终,将CRC值附加到原始数据后面形成完整的数据帧。数据帧的结构
数据帧的形式可以表示为:
T = D ⋅ x n + R T = D \cdot x^n + R T=D⋅xn+R
其中:
- D D D:原始数据。
- n n n:CRC值的位数。
- R R R:通过模2除法计算得到的CRC值。
接收端的验证逻辑
接收端接收到完整数据帧后,直接对整个数据帧进行CRC计算。如果数据帧在传输过程中未发生错误,则整个数据帧能够被生成多项式 P P P整除,余数为0。
通俗解释
假设我们有一个原始数据 D D D和一个生成多项式 P P P。发送端通过以下步骤构造数据帧:
- 将原始数据 D D D左移 n n n位,相当于给 D D D后面补了 n n n个0。
- 对左移后的数据用生成多项式 P P P进行模2除法运算,得到余数 R R R。
- 将余数 R R R附加到原始数据 D D D后面,形成完整的数据帧 T T T。
由于 T T T的设计方式( T = D ⋅ x n + R T = D \cdot x^n + R T=D⋅xn+R),它已经满足了模2除法的关系:
T m o d P = 0 T \mod P = 0 TmodP=0
也就是说,如果数据帧在传输过程中没有发生任何错误,那么接收端对接收到的数据帧 T T T再次进行模2除法运算时,余数必然为0。
举例说明
步骤 1:定义参数
- 原始数据: D = 0 x 34 = 0011 0100 D = 0x34 = 0011\ 0100 D=0x34=0011 0100。
- 生成多项式: P = 0 x 31 = 0011 0001 P = 0x31 = 0011\ 0001 P=0x31=0011 0001(CRC-8/MAXIM)。
- CRC值的位数: n = 8 n = 8 n=8。
步骤 2:发送端计算CRC值
将原始数据 D D D左移8位,相当于在其后面补8个0:
D ⋅ x 8 = 0011 0100 0000 0000 D \cdot x^8 = 0011\ 0100\ 0000\ 0000 D⋅x8=0011 0100 0000 0000对左移后的数据用生成多项式 P P P进行模2除法运算,得到余数 R = 0 x D F = 1101 1111 R = 0xDF = 1101\ 1111 R=0xDF=1101 1111。
将余数 R R R附加到原始数据 D D D后面,形成完整的数据帧:
T = D ⋅ x 8 + R = 0011 0100 1101 1111 = 34 D F T = D \cdot x^8 + R = 0011\ 0100\ 1101\ 1111 = 34DF T=D⋅x8+R=0011 0100 1101 1111=34DF步骤 3:接收端验证
接收端接收到的数据帧为 T = 34 D F = 0011 0100 1101 1111 T = 34DF = 0011\ 0100\ 1101\ 1111 T=34DF=0011 0100 1101 1111。接下来直接对整个数据帧 T T T进行模2除法运算:
- 使用生成多项式 P = 0 x 31 = 0011 0001 P = 0x31 = 0011\ 0001 P=0x31=0011 0001对数据帧 T T T进行模2除法运算。
- 计算结果表明,余数为0。
这说明数据帧 T T T能够被生成多项式 P P P整除,因此可以确认数据帧在传输过程中没有发生错误。
总结
通过上述例子可以看出,数据帧的设计方式决定了它能够被生成多项式整除(即模2除法余数为0)。如果数据帧在传输过程中发生了错误,例如某一位被翻转,则数据帧不再满足这种关系,模2除法的结果将不再是0,从而可以检测出错误的发生。
具体步骤
- 直接计算
对接收到的完整数据帧0011 0100 1101 1111
直接使用相同的CRC参数模型进行计算。 - 检查余数
如果计算得到的余数为0,则说明数据帧无误;否则,数据帧可能在传输过程中发生了错误。
不同位出错与余数的关系
现象描述
在实际应用中,如果数据帧中的某一位或多位发生错误,那么通过CRC计算得到的余数通常会与错误的位置相关联。具体来说,不同位的错误会导致不同的余数,而这种对应关系仅取决于所使用的CRC参数模型(如生成多项式、初始值等),而与原始数据无关。
数学证明
假设数据帧中的第
k
k
k位发生了错误,则可以将错误表示为一个二进制序列
E
E
E,其中只有第
k
k
k位为1,其余位均为0。错误后的数据帧可以表示为:
T
′
=
T
+
E
T' = T + E
T′=T+E
对
T
′
T'
T′进行模2除法运算时,余数为:
R
′
=
(
T
+
E
)
m
o
d
P
R' = (T + E) \mod P
R′=(T+E)modP
由于
T
m
o
d
P
=
0
T \mod P = 0
TmodP=0,因此:
R
′
=
E
m
o
d
P
R' = E \mod P
R′=EmodP
由此可见,余数
R
′
R'
R′仅与错误位置
k
k
k相关,而与原始数据
T
T
T无关。
总结
CRC校验的两种方法各有优劣:
- 分离比较法:需要对接收到的数据帧进行分离处理,适合于需要明确显示接收到的CRC值的场景。
- 整体运算法:直接对整个数据帧进行计算,无需分离处理,适合于快速判断数据帧是否正确的场景。
无论采用哪种方法,CRC校验的核心都在于利用生成多项式的数学特性,确保数据传输的可靠性。此外,CRC算法的检错能力与其参数模型密切相关,选择合适的参数模型对于提高系统性能至关重要。
2.5.5 CRC计算的C++实现及工具介绍
CRC(循环冗余校验)是一种广泛应用于数据通信和存储领域的错误检测技术。在实际开发中,为了验证自定义实现的正确性,通常需要借助一些标准工具进行对比测试。以下将详细介绍如何用C++实现CRC计算,并推荐几款常用的CRC计算工具。
C++实现CRC计算
- 核心思想
CRC计算的核心是基于模2除法的多项式运算。通过生成多项式对输入数据进行处理,最终得到一个固定长度的校验码。以下是C++实现CRC计算的基本步骤:
- 初始化CRC寄存器。
- 对输入数据逐位或逐字节进行处理。
- 根据REFIN参数决定是否翻转输入数据。
- 使用生成多项式进行模2除法运算。
- 根据REFOUT参数决定是否翻转输出结果。
- 最后与XOROUT值进行异或操作,得到最终的CRC值。
- 代码示例:CRC-8/MAXIM
以下是一个简单的C++实现CRC-8/MAXIM的代码示例:
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
// 按位翻转函数
uint8_t reverse_bits(uint8_t data) {
uint8_t result = 0;
for (int i = 0; i < 8; ++i) {
result = (result << 1) | (data & 1);
data >>= 1;
}
return result;
}
// CRC-8/MAXIM计算函数
uint8_t crc8_maxim(const vector<uint8_t>& data) {
uint8_t crc = 0x00; // INIT = 0x00
uint8_t poly = 0x31; // POLY = 0x31
for (auto byte : data) {
uint8_t byte_ref = reverse_bits(byte); // REFIN = TRUE
crc ^= byte_ref;
for (int i = 0; i < 8; ++i) {
if (crc & 0x80) {
crc = (crc << 1) ^ poly;
} else {
crc = (crc << 1);
}
crc &= 0xFF; // 保持8位
}
}
crc = reverse_bits(crc); // REFOUT = TRUE
return crc ^ 0x00; // XOROUT = 0x00
}
int main() {
vector<uint8_t> data = {0x34}; // 输入数据
uint8_t crc = crc8_maxim(data);
cout << "CRC-8/MAXIM: " << hex << (int)crc << endl;
return 0;
}
运行结果:
CRC-8/MAXIM: df
CRC计算工具推荐
-
在线计算工具
-
网址:CRC(循环冗余校验)在线计算_ip33.com
-
功能:
- 支持多种标准CRC模型(如CRC-8/MAXIM、CRC-16/CCITT等)。
- 允许用户自定义多项式、初始值、输入输出翻转等参数。
- 提供快速验证的功能,适用于开发者调试和学习。
-
离线计算工具
-
CRC_Calc v0.1.exe
- 功能强大,支持自定义CRC算法模型。
- 提供详细的参数配置选项,便于验证自定义实现的正确性。
-
GCRC.exe
- 简单易用,支持多种标准CRC模型。
- 输出结果清晰,适合快速验证。
-
格西CRC计算器
-
特点:
- 国产软件,界面友好。
- 支持多种标准CRC模型和自定义参数。
- 提供批量计算功能,适合处理大量数据。
2.5.6 总结:CRC校验的局限性与纠错原理
- CRC校验的局限性
尽管CRC校验是一种高效的错误检测方法,但它并不能100%保证数据的完整性。在极少数情况下,可能会出现数据中有错误但CRC校验结果仍为正确的现象。这种概率与以下因素有关:
- CRC的位数:位数越高,检错能力越强。
- 生成多项式的选择:不同的多项式具有不同的检错能力,标准多项式经过理论优化,能够提供更高的可靠性。
- 纠错原理
CRC校验本身主要用于错误检测,而非纠错。然而,在某些特定场景下,可以通过以下方式实现单一比特错误的纠正:
- 定位错误位置:利用接收到的数据帧重新计算CRC值,并比较计算结果与接收到的CRC值,确定错误发生的比特位置。
- 修正错误:根据错误位置翻转相应的比特,恢复原始数据。
这种纠错方法的前提是错误必须是单一比特错误,并且生成多项式的设计需要满足一定的数学条件(如汉明距离)。因此,在实际应用中,CRC校验更多地用于检测错误,而纠错功能通常由其他专门的编码技术(如Hamming码、Reed-Solomon码)来实现。
通过以上分析可以看出,CRC校验作为一种高效的数据完整性检测技术,在现代通信和存储系统中发挥了重要作用。在实际开发中,结合标准工具进行验证可以显著提高实现的可靠性,同时理解其局限性和纠错原理有助于更好地应用该技术。
参考资料:CRC校验原理及实现 - 知乎