0x00前言
写下这篇文章的主要目的有两点,第一就是之前有一份被吞掉的关于CRC32方面的文章;第二就是最近因为CRC16和CRC8导致了我又费了很多力气在上面,因此需要留以记录。本文分为两部分,前者讲述了相关的CRC常用算法与CRC的计算思想;后者阐述了一种可以计算出相关的CRC计算表的方式以及一种实现的例子。
阅读本文,您可能需要掌握的知识:
技能 | 熟练度 |
---|---|
英语 | 熟练 |
知识检索 | 熟练 |
逻辑计算 | 熟练 |
C语言 | 了解 |
0x01 CRC常用格式
CRC算是最简单、有粗暴的校验方式之一了。基本思维就是循环计算数据,因为存储的数据如果不一致,几乎不可能计算出相同的数据。唯一的可能就是存储的数据虽然不一致,但是只是位置不一致。为了避免这种情况的发生,CRC算法使用了乘除进行校验,并且将校验步骤分为初始值、系数。系数主要根据1的标志位,初始值和系数的不同会使计算出的数据不同。如0x1021就是一个CRC16系数,取自 X12+X5+X0
为1时的结果。而为了保证数据传输和兼容物理链接,加入了输入反转
、输出反转
、输出异或值
。
计算方式也很简单,主要是:
系数相除-->左移
,在经过循环计算之后,将最后的数据进行模2计算。也就是在对数据组做异或的方式进行校验。- 数据校验完成后输出的就是一个根据算法要求的输出长度的数据,常用的长度为8、16、32位。
- 最后根据实际需要决定是否需要进行输出、输入反向。
0x02 CRC自用格式
总结下来,CRC算法主要的参数为:初始值,系数、输入输出是否需要。而根据这些差别,出现了多达二十多种不同的CRC协议:
算法方式 | 初始值 | 系数 | 输入是否翻转 | 输出是否反转 | 输出异或值 |
---|---|---|---|---|---|
ITU-4 | 0x00 | 0x03 | √ | √ | 0x00 |
EPC-5 | 0x09 | 0x09 | × | × | 0x00 |
ITU-5 | 0x00 | 0x15 | √ | √ | 0x00 |
USB-5 | 0x1F | 0x05 | √ | √ | 0x1F |
ITU-6 | 0x00 | 0x03 | √ | √ | 0x00 |
MMC-7 | 0x00 | 0x09 | × | × | 0x00 |
Normal-8 | 0x00 | 0x07 | × | × | 0x00 |
ITU-8 | 0x00 | 0x07 | × | × | 0x55 |
ROHC-8 | 0xFF | 0x07 | √ | √ | 0x00 |
MAXIM-8 | 0x00 | 0x31 | √ | √ | 0x00 |
IBM-8 | 0x0000 | 0x8005 | √ | √ | 0x0000 |
MAXIM-16 | 0x0000 | 0x8005 | √ | √ | 0xFFFF |
USB-16 | 0xFFFF | 0x8005 | √ | √ | 0xFFFF |
MODBUS-16 | 0xFFFF | 0x8005 | √ | √ | 0x0000 |
CCITT-16 | 0x0000 | 0x1021 | √ | √ | 0x0000 |
CCITT-FALSE-16 | 0xFFFF | 0x1021 | √ | √ | 0x0000 |