如何理解CRC循环冗余校验
循环冗余校验(英语:Cyclic redundancy check,通称“CRC”)是一种产生定长校验码的算法,主要用来检测或校验数据传输或者保存后可能出现的错误。
它真的太常见了,上至应用软件通信和网络数据传输,下至芯片烧写、主从设备交互,好像凡是涉及通信,就免不了存在CRC校验。但它又太令人陌生了,习以为常地使用它,默认它的存在却不了解它的实现,想起来也的确是一件憾事,故而翻了翻论文,写点笔记放在这里。
1 资料追溯
据这篇文章
Tingilkar K, Reddy S K. Improvement Of Memory Data Corrections By Using CRC Technique For Fault Torrent Applications[J].
CRC理论最初由W. Wesley Peterson于1961年发表。
基本概念
简单说来,这个算法就是一个求给定序列的校验和(checksum)的算法:
CRC (Cyclic Redundancy Check) is a checksum algorithm.
它是定长多项式与输入比特流做模二除法以后的余数:
CRC is the remainder after division of a long input binary bitstream with fixed length polynomial.
我们也可以把CRC算法理解为一个有任意初值的移位寄存器。例如:输入比特流不断左移,在最左端的那一位满足条件时,通过规定的运算更新寄存器的值,最后寄存器里剩下的那个数就是我们要求的校验和:
CRC can also be considered as shift register. Original register value can be zero or non-zero.
Input bitstream is fed bit by bit and when it is finished, left register value is called ‘CRC’.
这里所说的“规定的运算”,就是让寄存器的值和多项式做异或运算:
Register is XORed with polynomial after every bit shift if out MSB value is ‘1’.
2 图解算法
需要形象一些的话,可以看下面这张图。输入比特流Input bits一位一位地进入一个左移寄存器(Left Shift Register, LSR),假如最左端出去的那一bit是1的话,左移寄存器的值就更新为当前LSR中的值与多项式异或的结果。然后再输入下一bit。
3 参数
从图解中可以知道,要实现CRC,至少需要知道左移寄存器的位宽和初值、用以进行异或运算的多项式(一个位宽与左移寄存器一致的0/1序列),此外再知道输入比特流和它的长度就可以进行CRC计算了。
/*
------------------------------------------------
CRC需要的参数 说明
------------------------------------------------
位宽 寄存器、多项式和校验和的位宽
输入 输入比特流的内容
输入长度 输出比特流的bit数
------------------------------------------------
*/
4 库
可以使用Github仓库:crc-lib-c
包含头文件就可以使用
#include <stdio.h>
#include <stdlib.h>
#include "crcLib.h"
int main()
{
uint8_t data; //输入
uint8_t crc; //输出
data = 0x34; //8-bits比特流输入(0011 0100)
crc = crc8_maxim(&data, 1);
printf("data:%02x, crc:%02x\n", data, crc);
return 0;
}
这个仓库里还有在线工具:CRC在线计算器