CRC算法原理与实现系列文章:
CRC算法原理与实现02——数学原理与模2运算 – 徐晓康的博客
CRC算法原理与实现03——参数说明、计算步骤与应用场景 – 徐晓康的博客
CRC算法原理与实现04——软硬件实现方法简介 – 徐晓康的博客
CRC算法原理与实现05——并行计算公式推导 – 徐晓康的博客
CRC算法原理与实现06——自编Python计算任意CRC – 徐晓康的博客
CRC算法原理与实现07——Verilog单步计算任意CRC – 徐晓康的博客
CRC算法原理与实现08——Verilog多步计算任意CRC – 徐晓康的博客
CRC算法原理与实现09——C语言计算任意CRC – 徐晓康的博客
前言
本文CRC的计算结果可与以下网站进行对比:
一. CRC算法的参数说明与计算步骤
前文已经说明了CRC算法的核心是模2除法,但目前广泛使用的CRC算法在进行模2除法之前和之后,还有一些反转或异或的操作。相关参数说明如下:
参数 | 概念 | 示例 | 作用 |
---|---|---|---|
多项式POLY(Polynomial) | CRC生成多项式,通常以十六进制表示,此时最高位1省略 | CRC-8,x8 + x2 + x + 1,对应二进制1_0000_0111,16进制表示0x07 | 算法核心,越长检错能力越强 |
输入反转REFIN(Reflection Input) | 是否对输入数据的每个字节进行位反转(最高位变最低位,次高位变次低位,依此类推) | 例如,输入数据 0x1234 (二进制:00010010_00110100 )反转后为 0x482C (二进制:01001000_00101100 ) |
简化硬件实现,适应串行通信的位顺序。 |
初始数据高位异或值INIT(Initial Value) | 在输入反转并且补0之后,将数据高位与初始值异或 | 例如,CRC-32 的初始值为 0xFFFFFFFF |
提高对输入数据前导0的敏感性 |
输出反转REFOUT(Reflection Output) | 是否对CRC 值整体进行位反转 | 例如,CRC 值 0x1234 (二进制:0001 0010 0011 0100 )反转后为 0x2C48 (二进制0010 1100 0100 1000 ) |
提高对某些类型错误(如突发错误)的检测能力 |
结果异或值XOROUT(XOR Output) | 在 CRC 计算与反转完成后,将 CRC 值与结果异或值进行按位异或操作 | 例如,CRC 值 0x12345678 与结果异或值 0xFFFFFFFF 异或后为 0xEDCBA987 |
避免全零 CRC 值,提高校验强度 |
计算CRC的步骤:(输入数据按字节进行位反转) → 在数据低位扩充CRC宽度个0 → 数据高位与初始数据高位异或值INIT异或 → 与生成多项式进行模2除法 → 得到余数即为CRC码 → (CRC码整体进行位反转) → 与结果异或值进行异或 → 最终CRC码。
注意:
-
输入数据非整数字节则高位补0到整数个字节。 -
()表示可选操作,有的CRC算法需要反转,有的不需要。 -
初始值为全0,则无需添加到数据高位,初始值全1才会对计算产生影响 -
与全0异或等价于原样保留,与全1异或等价于每位取反。
计算CRC的步骤总结如下图所示。虚线框表示可选步骤。
二. 特别注意——初始数据高位异或值
初始数据高位异或值,INIT,简称初始异或值
或初始值
,这个参数并不是什么CRC寄存器的初始值
,而是要与输入数据高位异或的初始值
。在后续文章中,会介绍CRC模2算法就相当于左移线性反馈移位寄存器(Linear Feedback Shift Register,简称LSFR)对每一位数据进行从高位到低位的左移反馈运算,如下图所示。
如果将这里的INIT理解为CRC寄存器初始值,当初始值为全1,对输入数据进行移位反馈运算得到的结果必然是错误的
。它就不是CRC寄存器初始值,而是要与补0后的输入数据高位异或的值,弄懂了这一点才能算对CRC,后续博客中在编写算法,推导CRC公式时也会有相关说明。
三. CRC算法计算示例
手算时注意10进制和16进制的对应关系。
3.1 以CRC-8为例
CRC-8 参数为:
-
多项式: 0x07
-
输入反转: False
-
初始异或值: 0x00
-
输出反转: False
-
结果异或值: 0x00
假设输入数据为 0x1234
,计算其 CRC 值:
-
输入反转:REFIN 为 False,输入保持原样;
-
高位与初始值异或:初始值全0,输入保持原样;
-
输入低位补0:
0x123400
; -
模2除多项式0x107:
0x123400 模2÷ 0x107
=0xF1
; -
输出反转:REFOUT为False,不进行输出反转;
-
输出异或:XOROUT全0,输出保持原样;
-
最终 CRC 值为
0xF1
。
用直接算CRC的网站和仅算模2除法的网址进行对比验证,结果如下:
3.2 以CRC-8-ROHC为例
CRC-8-ROHC 参数为:
-
多项式: 0x07
-
输入反转: True
-
初始异或值: 0xFF
-
输出反转: True
-
结果异或值: 0x00
假设输入数据为 0x1234
,计算其 CRC 值:
-
输入反转:REFIN 为 True,输入按字节进行反转, 0x12
二进制0001_0010,反转为0100_1000对应16进制0x48
,0x34
二进制0011_0100,反转为0010_1100对应16进制0x2C
,输入变为0x482C
; -
高位与初始值异或,初始值全1,此时异或等价于按位取反,0x48对应0100_1000,按位取反是1011_0111对应0xB7,输入变为 0xB72C
; -
输入低位补0: 0xB72C00
; -
模2除多项式0x107, 0xB72C00 模2÷ 0x107
=0xE0
; -
输出反转,REFOUT为True,输出整体反转,0xE0二进制1110_0000反转为0000_0111,对应 0x07
; -
输出异或:XOROUT全0,输出保持原样; -
最终 CRC 值为 0x07
。
用直接算CRC的网站和仅算模2除法的网址进行对比验证,结果如下:
四. 流行的CRC算法总结
CRC算法名称 | 宽度 | 多项式POLY | 初始值INIT | 结果异或值XOROUT | 输入反转REFIN | 输出反转REFOUT |
---|---|---|---|---|---|---|
CRC-4-ITU | 4 | 0x03 | 0x00 | 0x00 | 是 | 是 |
CRC-5-EPC | 5 | 0x09 | 0x09 | 0x00 | 否 | 否 |
CRC-5-ITU | 5 | 0x15 | 0x00 | 0x00 | 是 | 是 |
CRC-5-USB | 5 | 0x05 | 0x1F | 0x1F | 是 | 是 |
CRC-6-ITU | 6 | 0x03 | 0x00 | 0x00 | 是 | 是 |
CRC-7-MMC | 7 | 0x09 | 0x00 | 0x00 | 否 | 否 |
CRC-8 | 8 | 0x07 | 0x00 | 0x00 | 否 | 否 |
CRC-8-ITU | 8 | 0x07 | 0x00 | 0x55 | 否 | 否 |
CRC-8-ROHC | 8 | 0x07 | 0xFF | 0x00 | 是 | 是 |
CRC-8-MAXIM | 8 | 0x31 | 0x00 | 0x00 | 是 | 是 |
CRC-16 | 16 | 0x8005 | 0x0000 | 0x0000 | 是 | 是 |
CRC-16-MAXIM | 16 | 0x8005 | 0x0000 | 0xFFFF | 是 | 是 |
CRC-16-USB | 16 | 0x8005 | 0xFFFF | 0xFFFF | 是 | 是 |
CRC-16-MODBUS | 16 | 0x8005 | 0xFFFF | 0x0000 | 是 | 是 |
CRC-16-CCITT | 16 | 0x1021 | 0x0000 | 0x0000 | 是 | 是 |
CRC-16-CCITT-FALSE | 16 | 0x1021 | 0xFFFF | 0x0000 | 否 | 否 |
CRC-16-X25 | 16 | 0x1021 | 0xFFFF | 0xFFFF | 是 | 是 |
CRC-16-XMODEM | 16 | 0x1021 | 0x0000 | 0x0000 | 否 | 否 |
CRC-16-DNP | 16 | 0x3D65 | 0x0000 | 0xFFFF | 是 | 是 |
CRC-32 | 32 | 0x04C11DB7 | 0xFFFFFFFF | 0xFFFFFFFF | 是 | 是 |
CRC-32-MPEG-2 | 32 | 0x04C11DB7 | 0xFFFFFFFF | 0x00000000 | 否 | 否 |
CRC-64-ISO | 64 | 0x00000000 00000001B |
64位全0 | 64位全0 | 是 | 是 |
CRC-64-ECMA | 64 | 0x42F0E1EB A9EA3693 |
64位全0 | 64位全0 | 是 | 是 |
CRC-64-WE | 64 | 0x42F0E1EB A9EA3693 |
64位全1 | 64位全1 | 是 | 是 |
五. CRC算法的应用场景
CRC算法名称 | 别名 | 说明 |
---|---|---|
CRC-4-ITU | – | 用于 ITU-T 标准,常见于通信协议中的数据校验。 |
CRC-5-EPC | – | 用于 EPCglobal 标准,主要用于 RFID 标签的数据校验。 |
CRC-5-ITU | – | 用于 ITU-T 标准,常见于通信协议中的数据校验。 |
CRC-5-USB | – | 用于 USB 协议,确保数据传输的完整性。 |
CRC-6-ITU | – | 用于 ITU-T 标准,常见于通信协议中的数据校验。 |
CRC-7-MMC | – | 用于 MMC/SD 存储卡协议,确保存储数据传输的完整性。 |
CRC-8 | CRC-8-SAE-J1850 | 广泛应用于多种场景。 |
CRC-8-ITU | CRC-8-I-CODE | 用于 ITU-T 标准,常见于通信协议中的数据校验。 |
CRC-8-ROHC | – | 用于 ROHC(鲁棒性头压缩)协议,确保数据头部的完整性。 |
CRC-8-MAXIM | CRC-8-Dallas,CRC-8-IBUTTON | 用于 Maxim 的 1-Wire 总线协议,确保数据传输的可靠性。 |
CRC-16 | CRC-16-IBM,CRC-16-ANSI | 广泛应用于多种场景。 |
CRC-16-MAXIM | CRC-16-Dallas | 用于 Maxim 的 1-Wire 总线协议,确保数据传输的可靠性。 |
CRC-16-USB | – | 用于 USB 协议,确保数据传输的完整性。 |
CRC-16-MODBUS | – | 用于 Modbus 通信协议,确保工业通信数据的完整性。 |
CRC-16-CCITT | CRC-CCITT,KERMIT,CRC-16-CCITT-TRUE | 广泛用于通信协议中的数据校验。 |
CRC-16-CCITT-FALSE | XMODEM | 用于通信协议,初始值为 0xFFFF,输入输出不反转。 |
CRC-16-X25 | CRC-16-IBM-SDLC,CRC-16-ISO-HDLC | 用于 X.25 协议,确保网络层数据传输的完整性。 |
CRC-16-XMODEM | ZMODEM | 常用于文件传输协议(如 XMODEM,ZMODEM)中,确保数据传输的完整性。 |
CRC-16-DNP | – | 用于 DNP3 协议,确保工业通信数据的完整性。 |
CRC-32 | CRC-32/ADCCP,CRC-32-PKZIP | 广泛用于 ZIP,PNG 等文件校验,以及网络协议中的数据完整性校验。 |
CRC-32-MPEG-2 | – | 用于 MPEG-2 协议,确保音视频数据传输的完整性。 |
CRC-64-ISO | – | 用于 ISO 3309 标准,广泛应用于文件校验和数据库一致性检查。 |
CRC-64-ECMA | – | 用于 ECMA-182 标准,常见于分布式存储和数据传输协议中。 |
CRC-64-WE | CRC-64-XZ | 通用数据校验(如数据库、文件系统),也用于 XZ Utils 文件压缩工具中的数据校验 |
如果本文对你有所帮助,欢迎点赞、转发、收藏、评论让更多人看到,赞赏支持就更好了。
如果对文章内容有疑问,请务必清楚描述问题,留言评论或私信告知我,我看到会回复。

徐晓康的博客持续分享高质量硬件、FPGA与嵌入式知识,软件,工具等内容,欢迎大家关注。