什么是CRC校验?

CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。

CRC校验原理:

其根本思想就是先在要发送的帧后面附加一个数。(这个就是用来校验的校验码,但要注意,这里的数也是二进制序列的,下同),生成一个新帧发送给接收端。

当然,这个附加的数不是随意的,它要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除(注意,这里不是直接采用二进制除法,而是采用一种称之为“模2除法”)。

到达接收端后,再把接收到的新帧除以(同样采用“模2除法”)这个选定的除数。因为在发送端发送数据帧之前就已通过附加一个数,做了“去余”处理(也就已经能整除了),所以结果应该是没有余数。如果有余数,则表明该帧在传输过程中出现了差错。

模2除法:

模2除法与算术除法类似,但每一位除的结果不影响其它位,即不向上一位借位,所以实际上就是异或。在循环冗余校验码(CRC)的计算中有应用到模2除法。

例:

CRC8算法:

需求数据:

多项式:x8+x5+x4+1(二进制为:100110001)                           0x31(0x131)

计算一个字节:0x11   (二进制为:00010001)

计算步骤:

A、 因为采用顺序异或,所以需要计算的数据左移8位, 移位后数据为:0001 0001 0000 0000

B、 先进行高9bit异或(多项式为9bit),0001 0001 0000 0000,因为高9bit的 最高bit为0,不需要进行异或,同理,接下来的两bit也是0,也不需要进行进行异或。 这样处理后数据为:1 0001 0000 0000;

C、 接下来最高位为1,需要进行异或操作了

从上面的计算过程可以看到,多项式最高位为1,遇到需要异或数据最高位为1时, 才进行异或计算,并且异或后,最高位就为0了,最高位为0,下次也不需要异或了, 这样需要采用代码计算的方式,就可以把最高位去掉,不需要异或,最后结果也是一样的。

代码实现:

a、是计算一个字节数据的crc结果,如果是计算多个字节的crc结果,也是比较简单

  1. unsigned char cal_table_high_first(unsigned char value)
  2. {
  3. unsigned char i, crc;
  4.  
  5. crc = value; //0001 0001
  6. /* 数据往左移了8位,需要计算8次 */
  7. for (i=; i>; --i)
  8. {
  9. if (crc & 0x80) /* 判断最高位是否为1 */
  10. {
  11. /* 最高位为1,不需要异或,往左移一位,然后与0x31异或 */
  12. /* 0x31(多项式:x8+x5+x4+1,100110001),最高位不需要异或,直接去掉 */
         /*参见C步骤*/
  13. crc = (crc << ) ^ 0x31; }
  14. else
  15. {
  16. /* 最高位为0时,不需要异或,整体数据往左移一位 */
  17. crc = (crc << );
  18. }
  19. }
  20.  
  21. return crc;
  22. }

的,先计算第一个字节的crc结果,然后把第一个字节的crc结果与第二个字节进行异或, 异或后的值再进行一次crc计算就可以了,多个字节也是反复这过程就好,如下为多个字节 的crc校验代码:

  1. unsigned char crc_high_first(unsigned char *ptr, unsigned char len)
  2. {
  3. unsigned char i;
  4. unsigned char crc=0x00 /* 计算的初始crc值 */
  5.  
  6. while(len--)
  7. {
  8. crc ^= *ptr++; /* 每次先与需要计算的数据异或,计算完指向下一数据 */
    /ptr应为需要计算的数据的每个字节的指针*/

  9. for (i=; i>; --i) /* 下面这段计算过程与计算一个字节crc一样 */
  10. {
  11. if (crc & 0x80)
  12. crc = (crc << ) ^ 0x31;
  13. else
  14. crc = (crc << );
  15. }
  16. }
  17.  
  18. return (crc);
  19. }

上面的crc计算是纯采用逻辑运行的方式,可以看到,需要的运行量也是不少的,每一个字节都需要进行8次判断、移位、或异或操作。可以采用查表法,大大减少计算量,先计算出 0x00~0xFF每一个字节的crc校验结果,后面就可以通过表来查出每个字节的crc结果,大大 减少计算量。

下面是一个表生成程序: (生成表对应多项式:0x31(多项式:x8+x5+x4+1,100110001))

  1. void create_crc_table(void)
  2. {
  3. unsigned short i;
  4. unsigned char j;
  5.  
  6. for (i=; i<=0xFF; i++)
  7. {
  8. if ( == (i%))
  9. printf("\n");
  10.  
  11. j = i&0xFF;
  12. printf("0x%.2x, ", cal_table_high_first (j)); /*依次计算每个字节的crc校验值*/
  13. }
  14. }

得到的表整理后如下:

  1. static const unsigned char crc_table[] =
  2. {
  3. 0x00,0x31,0x62,0x53,0xc4,0xf5,0xa6,0x97,0xb9,0x88,0xdb,0xea,0x7d,0x4c,0x1f,0x2e,
  4. 0x43,0x72,0x21,0x10,0x87,0xb6,0xe5,0xd4,0xfa,0xcb,0x98,0xa9,0x3e,0x0f,0x5c,0x6d,
  5. 0x86,0xb7,0xe4,0xd5,0x42,0x73,0x20,0x11,0x3f,0x0e,0x5d,0x6c,0xfb,0xca,0x99,0xa8,
  6. 0xc5,0xf4,0xa7,0x96,0x01,0x30,0x63,0x52,0x7c,0x4d,0x1e,0x2f,0xb8,0x89,0xda,0xeb,
  7. 0x3d,0x0c,0x5f,0x6e,0xf9,0xc8,0x9b,0xaa,0x84,0xb5,0xe6,0xd7,0x40,0x71,0x22,0x13,
  8. 0x7e,0x4f,0x1c,0x2d,0xba,0x8b,0xd8,0xe9,0xc7,0xf6,0xa5,0x94,0x03,0x32,0x61,0x50,
  9. 0xbb,0x8a,0xd9,0xe8,0x7f,0x4e,0x1d,0x2c,0x02,0x33,0x60,0x51,0xc6,0xf7,0xa4,0x95,
  10. 0xf8,0xc9,0x9a,0xab,0x3c,0x0d,0x5e,0x6f,0x41,0x70,0x23,0x12,0x85,0xb4,0xe7,0xd6,
  11. 0x7a,0x4b,0x18,0x29,0xbe,0x8f,0xdc,0xed,0xc3,0xf2,0xa1,0x90,0x07,0x36,0x65,0x54,
  12. 0x39,0x08,0x5b,0x6a,0xfd,0xcc,0x9f,0xae,0x80,0xb1,0xe2,0xd3,0x44,0x75,0x26,0x17,
  13. 0xfc,0xcd,0x9e,0xaf,0x38,0x09,0x5a,0x6b,0x45,0x74,0x27,0x16,0x81,0xb0,0xe3,0xd2,
  14. 0xbf,0x8e,0xdd,0xec,0x7b,0x4a,0x19,0x28,0x06,0x37,0x64,0x55,0xc2,0xf3,0xa0,0x91,
  15. 0x47,0x76,0x25,0x14,0x83,0xb2,0xe1,0xd0,0xfe,0xcf,0x9c,0xad,0x3a,0x0b,0x58,0x69,
  16. 0x04,0x35,0x66,0x57,0xc0,0xf1,0xa2,0x93,0xbd,0x8c,0xdf,0xee,0x79,0x48,0x1b,0x2a,
  17. 0xc1,0xf0,0xa3,0x92,0x05,0x34,0x67,0x56,0x78,0x49,0x1a,0x2b,0xbc,0x8d,0xde,0xef,
  18. 0x82,0xb3,0xe0,0xd1,0x46,0x77,0x24,0x15,0x3b,0x0a,0x59,0x68,0xff,0xce,0x9d,0xac
  19. };

采用查表法计算crc代码如下:  

  1. unsigned char cal_crc_table(unsigned char *ptr, unsigned char len)
  2. {
  3. unsigned char crc = 0x00;
  4.  
  5. while (len--)
  6. {
  7. crc = crc_table[crc ^ *ptr++];
  8. }
  9. return (crc);
  10. }

反序异或的计算

反序异或与顺序异或差异在数据先判断最低位,并且数据是向右移 的,并且多项式数据位需要高低位反转一下。 还是以多项式:x8+x5+x4+1(二进制为:100110001)为例:则计算一个字节的crc校验代码如下:

  1. unsigned char cal_table_low_first(unsigned char value)
  2. {
  3. unsigned char i, crc;
  4.  
  5. crc = value;
  6. /* 同样需要计算8次 */
  7. for (i=; i>; --i)
  8. {
  9. if (crc & 0x01) /* 反序异或变成判断最低位是否为1 */
  10. /* 数据变成往右移位了 */
  11. /* 计算的多项式从0x31(0011 0001)变成了0x8C (1000 1100) */
  12. /* 多项式值,原来的最高位变成了最低位,原来的最低位变成最高位,8位数据高低位交换一下位置 */
  13. crc = (crc >> ) ^ 0x8C;
  14. else
  15. crc = (crc >> );
  16. }
  17.  
  18. return crc;
  19. }

至于多个字节的crc校验及crc数据表的生成,只要把单个字节的计算方式替换一下顺序的 计算方式即可,这里就不再列出。所以,只要明确了crc校验使用的多项式,高位先校验 还是低位先校验,计算crc的初始值是什么,那crc的计算就变得很简单了。

***********************************************************************************************************************
待更新,添加CRC32代码和运行结果

参考:https://blog.csdn.net/d_leo/article/details/73572373     https://blog.csdn.net/zjli321/article/details/52998468

CRC校验8的更多相关文章

  1. 文档:网络通讯包结构(crc校验,加解密)

    一直想把这个流程整理一下. 包结构: 包 对(datacrc+protoID+dataSize)组成的byte[] 进行crc计算而得到 对(数据内容)进行crc计算而得到 协议号 数据内容的字节长度 ...

  2. CRC校验码原理、实例、手动计算

    目录一.CRC16实现代码二.CRC32编码字符表三.CRC校验码的手动计算示例四.CRC校验原理五.CRC的生成多项式参考 一.CRC16实现代码 思路:取一个字符(8bit),逐位检查该字符,如果 ...

  3. 物联网平台设计心得:你所不知道的CRC校验

    在物联网平台设计过程中,我的中间件一方面需要处理来自于硬件端的包,另一方面需要处理来自于用户端的包,用户端包括web端和手机端等等.所以编写一个统一的CRC认证是非常必须要. 那么,在设计开始,CRC ...

  4. CRC校验代码实现

    1.CRC校验简介 CRC就是块数据的计算值,它的全称是“Cyclic Redundancy Check”,中文名是“循环冗余码”.CRC校验是数据通讯中最常采用的校验方式.在嵌入式软件开发中,经常要 ...

  5. CRC校验码

    循环冗余校验码(CRC)的基本原理是:在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码也叫(N,K)码.对于一个给定的(N,K)码,可以证明存在一个最高次幂为R的多项式G(x)(R ...

  6. C# CRC校验的一点感悟

    今天在鼓捣一个手持操作器的时候,遇到一点问题,记录一下今天的经验包 由于之前公司产品在校验时基本上都是和校验,今天在准备用C#模拟一个古董操作器的时候,却遇到一个问题,模拟器发出的数据,主板一律不回复 ...

  7. CRC校验源码分析

    这两天做项目,需要用到 CRC 校验.以前没搞过这东东,以为挺简单的.结果看看别人提供的汇编源程序,居然看不懂.花了两天时间研究了一下 CRC 校验,希望我写的这点东西能够帮助和我有同样困惑的朋友节省 ...

  8. 在线CRC校验

    在线CRC校验: http://www.lammertbies.nl/comm/info/crc-calculation.html

  9. CRC校验

    小试一下CRC校验的verilog实现,采用最stupid的直接法. /* date : 2014/06/06 designer : pengxiaoen virsion : Altera-Model ...

  10. 网络通信 --> CRC校验

    CRC校验 一.什么是CRC校验     循环校验码(Jyclic Redundancy Check,简称CRC码): 是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意 ...

随机推荐

  1. Daily paper -Science 2006: Experimental Study of Inequality and Unpredictability in an Artificial Cultural Market (探究群体行为对商品销量的影响)

    论文:      Experimental Study of Inequality and Unpredictability in an Artificial Cultural Market 发表期刊 ...

  2. Java—IO流 RandomAccessFile类

    RandomAccessFile java提供的对文件内容的访问,既可以读文件,也可以写文件. 支持随机访问文件,可以访问文件的任意位置. java文件模型,在硬盘上的文件是byte byte byt ...

  3. 在Eclipse中安装JSHint插件

    离线安装 1.下载插件包 http://download.eclipsesource.com/~rsternberg/jshint-eclipse-0.9.8.20130728-0004-b94b44 ...

  4. docker 部署 nginx+php+mysql

    系统:centos7 使用root账户 开放80端口 firewall-cmd --zone=public --add-port=80/tcp --permanent 安装docker yum ins ...

  5. python26 re正则表达式

    #coding:utf-8 #/usr/bin/python """ 2018-11-25 dinghanhua re """ import ...

  6. POJ-1080 Human Gene Functions---类似LCS

    题目链接: https://cn.vjudge.net/problem/POJ-1080 题目大意: 给定两组序列,要你求出它们的最大相似度,每个字母与其他字母或自身和空格对应都有一个打分,求在这两个 ...

  7. oc 无中生有添加协议(使已有函数符合协议)

    class_addProtocol([UIButton class],@protocol(UIButtonExport)); @protocol UIButtonExport <JSExport ...

  8. redis未授权访问getshell

    redis未授权访问的问题一年前就爆了,当时刚开始学安全,还不太懂.今天借着工作的机会来搞一把,看看能不能拿下一台服务器.其实前几天就写好了一直想找个实际环境复现一下,一直没有找到,只说下大致思路. ...

  9. 2018.9.17 面试问题-----如何对List集合中的元素进行排序?

    Collections对List集合中的数据进行排序 有时候需要对集合中的元素按照一定的规则进行排序,这就需要用到 Java中提供的对集合进行操作的工具类Collections,其中的sort方法 先 ...

  10. Docker 常用指令

    1.检查内核版本,必须是3.10及以上uname ‐r2.安装dockeryum install docker3.输入y确认安装4.启动docker[root@localhost ~]# system ...