文章目录

  • 目录
  • 前言
  • CRC算法简介
  • CRC参数模型
  • CRC计算
  • CRC校验
  • CRC计算的C语言实现
  • CRC计算工具
  • 总结
  • 参考资料

目录

  • 前言
  • CRC算法简介
  • CRC计算
  • CRC校验
  • CRC计算的C语言实现
  • CRC计算工具
  • 总结

前言

最近的工作中,要实现对通信数据的CRC计算,所以花了两天的时间好好研究了一下,周末有时间整理了一下笔记。

一个完整的数据帧通常由以下部分构成:

校验位是为了保证数据在传输过程中的完整性,采用一种指定的算法对原始数据进行计算,得出的一个校验值。接收方接收到数据时,采用同样的校验算法对原始数据进行计算,如果计算结果和接收到的校验值一致,说明数据校验正确,这一帧数据可以使用,如果不一致,说明传输过程中出现了差错,这一帧数据丢弃,请求重发。

常用的校验算法有奇偶校验、校验和、CRC,还有LRC、BCC等不常用的校验算法。

以串口通讯中的奇校验为例,如果数据中1的个数为奇数,则奇校验位0,否则为1。

例如原始数据为:0001 0011,数据中1的个数(或各位相加)为3,所以奇校验位为0。这种校验方法很简单,但这种校验方法有很大的误码率。假设由于传输过程中的干扰,接收端接收到的数据是0010 0011,通过奇校验运算,得到奇校验位的值为0,虽然校验通过,但是数据已经发生了错误。

校验和同理也会有类似的错误:

一个好的校验校验方法,配合数字信号编码方式,如(差分)曼彻斯特编码,(不)归零码等对数据进行编码,可大大提高通信的健壮性和稳定性。例如以太网中使用的是CRC-32校验,曼彻斯特编码方式。本篇文章介绍CRC校验的原理和实现方法。

CRC算法简介

循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。

CRC校验计算速度快,检错能力强,易于用编码器等硬件电路实现。从检错的正确率与速度、成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC 成为计算机信息通信领域最为普遍的校验方式。常见应用有以太网/USB通信,压缩解压,视频编码,图像存储,磁盘读写等。

CRC参数模型

不知道你是否遇到过这种情况,同样的CRC多项式,调用不同的CRC计算函数,得到的结果却不一样,而且和手算的结果也不一样,这就涉及到CRC的参数模型了。计算一个正确的CRC值,需要知道CRC的参数模型。

一个完整的CRC参数模型应该包含以下信息:WIDTH,POLY,INIT,REFIN,REFOUT,XOROUT。

  • NAME:参数模型名称。

  • WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位

  • POLY:十六进制多项式,省略最高位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参数模型:

CRC校验在电子通信领域非常常用,可以说有通信存在的地方,就有CRC校验:

  • 美信(MAXIM)的芯片DS2401/DS18B20,都是使用的CRC-8/MAXIM模型
  • SD卡或MMC使用的是CRC-7/MMC模型
  • Modbus通信使用的是CRC-16/MODBUS参数模型
  • USB协议中使用的CRC-5/USB和CRC-16/USB模型
  • STM32自带的硬件CRC计算模块使用的是CRC-32模型

至于多项式的选择,初始值和异或值的选择,输入输出是否翻转,这就涉及到一定的编码和数学知识了。感兴趣的朋友,可以了解一下每个CRC模型各个参数的来源。至于每种参数模型的检错能力、重复率,需要专业的数学计算了,不在本文讨论的范畴内。

CRC计算

好了,了解了CRC参数模型知识,下面手算一个CRC值,来了解CRC计算的原理。

问:原始数据:0x34,使用CRC-8/MAXIN参数模型,求CRC值?

答:根据CRC参数模型表,得到CRC-8/MAXIN的参数如下:

POLY = 0x31 = 0011 0001(最高位1已经省略)
INIT = 0x00
XOROUT = 0x00
REFIN = TRUE
REFOUT = TRUE

有了上面的参数,这样计算条件才算完整,下面来实际计算:

0.原始数据 = 0x34 = 0011 0100,多项式 = 0x31 = 1 0011 0001
1.INIT = 00,原始数据高8位和初始值进行异或运算保持不变。
2.REFIN为TRUE,需要先对原始数据进行翻转:0011 0100 > 0010 1100
3.原始数据左移8位,即后面补8个0:0010 1100 0000 0000
4.把处理之后的数据和多项式进行模2除法,求得余数:
原始数据:0010 1100 0000 0000 = 10 1100 0000 0000
多项式:1 0011 0001
模2除法取余数低8位:1111 1011
5.与XOROUT进行异或,1111 1011 xor 0000 0000 = 1111 1011
6.因为REFOUT为TRUE,对结果进行翻转得到最终的CRC-8值:1101 1111 = 0xDF
7.数据+CRC:0011 0100 1101 1111 = 34DF,相当于原始数据左移8位+余数。

模2除法求余数:

验证手算结果:

可以看出是一致的,当你手算的结果和工具计算结果不一致时,可以看看INIT,XOROUT,REFINT,REFOUT这些参数是否一致,有1个参数不对,计算出的CRC结果都不一样。

CRC校验

上面通过笔算的方式,讲解了CRC计算的原理,下面来介绍一下如何进行校验。

按照上面CRC计算的结果,最终的数据帧:0011 0100 1101 1111 = 34DF,前8位0011 0100是原始数据,后8位1101 1111 是 CRC结果。

接收端的校验有两种方式,一种是和CRC计算一样,在本地把接收到的数据和CRC分离,然后在本地对数据进行CRC运算,得到的CRC值和接收到的CRC进行比较,如果一致,说明数据接收正确,如果不一致,说明数据有错误。

另一种方法是把整个数据帧进行CRC运算,因为是数据帧相当于把原始数据左移8位,然后加上余数,如果直接对整个数据帧进行CRC运算(除以多项式),那么余数应该为0,如果不为0说明数据出错。

而且,不同位出错,余数也不同,可以证明,余数与出错位数的对应关系只与CRC参数模型有关,而与原始数据无关。

CRC计算的C语言实现

无论是用C还是其他语言,实现方法网上很多,这里我找了一个基于C语言的CRC计算库,里面包含了常用的21个CRC参数模型计算函数,可以直接使用,只有crcLib.ccrcLib.h两个文件。

  • GitHub地址:https://github.com/whik/crc-lib-c
  • Gitee地址:https://gitee.com/whik/crc-lib-c
    使用方法非常简单:
#include <stdio.h>
#include <stdlib.h>
#include "crcLib.h"int main()
{uint8_t LENGTH = 10;uint8_t data[LENGTH];uint8_t crc;for(int i = 0; i < LENGTH; i++){data[i] = i*5;printf("%02x ", data[i]);}printf("\n");crc = crc8_maxim(data, LENGTH);printf("CRC-8/MAXIM:%02x\n", crc);return 0;
}

计算结果:

CRC计算工具

下面这几款工具都可以自定义CRC算法模型,而且都有标准CRC模型可供选择。如果自己用C语言或者Verilog实现校验算法时,非常适合作为标准答案进行验证。

  • 在线计算:www.ip33.com/crc.html
  • 离线计算工具:CRC_Calc v0.1.exe或者GCRC.exe

格西CRC计算器:

总结

CRC校验并不能100%的检查出数据的错误,非常低的概率会出现CRC校验正确但数据中有错误位的情况。这和CRC的位数,多项式的选择等等有很大的关系,所以在实际使用中尽量选择标准CRC参数模型,这些多项式参数都是经过理论计算得出的,可以提高CRC的检错能力。CRC校验可以检错,也可以纠正单一比特的错误,你知道纠错的原理吗?

参考资料

  • https://www.cnblogs.com/liushui-sky/p/9962123.html
  • https://segmentfault.com/a/1190000018094567

CRC校验原理及其C语言实现相关推荐

  1. c语言用CRC校验FCS序列,CRC校验原理与其C语言实现

    CRC校验码的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+ r)位,最后发 ...

  2. 一文详解循环冗余校验校验算法(CRC校验)及C语言代码的实现 ---- 以CRC-16/MODBUS为例讲解

    一.概述 现在的产品开发过程中,无论是数据的储存还是传输,都需要确保数据的准确性,所以就需要在数据帧后面附加一串校验码,方便接收方使用校验码校验接收到的数据是否是正确的. 常用的校验方式有奇偶校验.异 ...

  3. c语言 x16 x15 x2 1,CRC算法原理及C语言实现

    CRC算法原理及C语言实现 摘 要 本文从理论上推导出CRC算法实现原理,给出三种分别适应不同计算机或微控制器硬件环境的C语言程序.读者更能根据本算法原理,用不同的语言编写出独特风格更加实用的CRC计 ...

  4. 简单易懂的CRC校验原理阐述

    不要跑,CRC没这么难!(简单易懂的CRC原理阐述) 网上大多的教材都是面向大佬的很多细节原理都没有讲清楚,对于我们这些新萌菜鸟们实在太不友好了.于是我写一篇相对轻松易懂的博客,希望能对学习CRC的朋 ...

  5. 【个人学习总结】CRC校验原理及实现

    [个人学习总结]CRC校验原理及实现 一.CRC校验原理[理论篇] 1.硬核视频讲解[重点看,非常非常好!!!] 2.基础文章[略看] 3.深入文章!!![代码.查表法有点看不懂,跨越有点大] 理解重 ...

  6. c语言 checksum,crc校验方法,用c语言实现源代码(CRC checksum method, using C language source code).doc...

    crc校验方法,用c语言实现源代码(CRC checksum method, using C language source code) crc校验方法,用c语言实现源代码(CRC checksum ...

  7. CRC校验原理及两种代码实现方法(c语言和labview实现)

    CRC校验原理及代码实现 目录 背景 原理 模2除法 多项式 计算流程 代码实现() c语言实现 c语言测试结果 labview实现 labview测试结果 目录 背景 在进行数据传输时,为了避免数据 ...

  8. CRC校验原理及STM32 IAP在线升级程序

    CRC校验原理: 什么是CRC校验? CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能,对数据 ...

  9. 编写一个字节数的rtu C语言校验程序,Modbus通信协议中CRC校验的快速C语言算法

    Modbus通信协议中CRC校验的快速C语言算法 2004年第11期 福 建 电 脑 63 Modbus通信协议中CRC校验的快速C语言算法 孟开元 (西安石油大学计算机学院陕西西安710065) [ ...

  10. CRC校验原理及CRC-8简单校验函数设计

    CRC校验原理及CRC-8简单校验函数设计 CRC为循环冗余校验码,是一种常用的.具有检错.纠错能力的校验码.通常发送方在发送的数据之后,附上其CRC校验码.接收方收到数据后,也做同样的CRC校验,得 ...

最新文章

  1. Hover伪类在IE6中的实现
  2. ZJOI2018 Round2 游记
  3. FreeEIM 来点新知识iOS UIScrollView详解
  4. 题解 P5065 【[Ynoi2014]不归之人与望眼欲穿的人们】
  5. 关于Java中的GUI事件处理
  6. for里面嵌套if_求求你们了,别再写满屏的 if/ else 了!
  7. 学习webbench需要掌握的基础知识(webbench源代码学习心得)
  8. Linux下mysql主从同步备份master-slave详细配置
  9. Linux中vim编辑器常用命令、文件查找、磁盘挂载、用户管理
  10. IPOP下的tcl脚本使用
  11. Scratch3.0创意编程(基础篇):第3课 弹球游戏
  12. Html实现Excel锁定表头效果
  13. 分享一个2.4G无线麦克风音频接收器的成功案例
  14. 《计算机网络实验》网络参数配置与常用网络命令使用,超级详细教程
  15. dl320服务器内存型号,HP DL320 G5 1U XEON 3040/2GB内存/500G SATA 双核服务器
  16. php毕业论文结论,科学网—如何写好学位论文的摘要和结论 - 王东升的博文
  17. tp5简单的图片上传
  18. c++可视化性能测试
  19. 如何用计算机做大爆炸模拟,法国完成首个宇宙结构计算机模型 模拟大爆炸至今...
  20. 用vue+element-ui快速写一个注册登录页面

热门文章

  1. iphone iOS 更换手机铃声 免itunes
  2. java 微信退款接口_微信APP支付和退款(JAVA)
  3. 用计算机公式表白,昨天,我用IF函数表白成功了!
  4. docker搭建snipe-it
  5. 使用css3制作正六面体
  6. 激光雷达移动状态下的数据矫正
  7. w ndows系统启动日志ID,WIN7日志总能看到 特殊登陆 事件ID 4672,是怎么回事?
  8. pytorch学习(二):mnist手写数字数据集训练和测试(一)mnist数据集分析
  9. [資源]RAID是什么意思?RAID的应用
  10. 讯飞、有道、谷歌、微软语音sdk集成总结