参考:https://blog.csdn.net/niepangu/article/details/45499383

计算CRC的过程,就是用一个特殊的“除法”,来得到余数,这个余数就是CRC。 
它不是真正的算术上的除法!过程和算术除法过程一样,只是加减运算变成了XOR(异或)运算! 
 
算术上的除法: 
120÷9=13 余 3,120是被除数,9是除数,13是商,3是余数。念作120除以9,或者9除120,或
者9去除120!(除法的过程就不写了) 
这个除法计算机当然会做,但是做起来很麻烦,因为减法有借位,很耗时间和指令! 
所以,计算CRC也是除法,但是用XOR来代替减法,这就简单多了!

CRC的除法: 
120÷9=14 余 6,商、余数和算术除法不一定相同!!因为除法用的是XOR,而不是真正的减法。 
以二进制模拟这个计算过程:

120 二进制:1111000 、除数9 二进制:1001 、商 14 二进制:1110 余数6 二进制:110

从高位1111开始,每次进行一次XOR 的到的值后,去掉最高位加入下一位,每加一次进行一次XOR运算。

1111

^1001

--------------

0110

第一次XOR后得到0110,去掉最高位0,加入下一位0, 得1100 ,这样最高位是1,所以下个商是1 ,用^1001【很明显保留的位数与1001 保持一致】

1100

^1001

--------------

0101

第二次XOR ,去掉最高位,加入下一位0,得1010 ,这样最高位是1,所以下个商是1 ,用^1001

1010

^ 1001

---------------

0011

第三次XOR,去掉最高位,加入下一位0,得0110 ,这样最高位是1,所以下个商是0 ,用^0000

0110

^ 0000

-------------

0110

最后一次XOR后得到0110,最高位的0可以消掉了,得到余数为110,即6 
注意,余数不是0110,而是110,因为最前面那个0已经被XOR后消掉了!

可见,除法(XOR)的目的是逐步消掉最高位的1或0! 
由于过程是XOR的,所以商是没有意义的,我们不要。我们要的是余数。 
 
余数110是1111000的CRC吗?不是! 
余数110是1111(即十进制15)的CRC!!! 
为什么?因为CRC是和数据一起传送的,所以数据后面要加上CRC。 
数据1111加上CRC110后,变成1111110,再传送。接收机收到1111110后,除以除数1001,余数为
000,正确;如果余数不为0,则说明传送的数据有误!这样完成CRC校验。 
即发送端要发送1111,先在1111后加000,变成1111000,再除以1001得到余数110,这个110
就是CRC,将110加到数据后面,变成1111110,发送出去。 
接收端收到1111110,用它除以1001,计算得余数为000,就说明收到的数据正确。 
所以原始数据后面要先扩展出3位0,以容纳CRC值! 
会发现,在上面的除法过程中,这3位0,能保证所有的4个数据位在除法时都能够被处理到!不然做
一次除法就到结果了,那是不对的。这个概念后面要用到。

二、  生成项 
上面例子中,生成项是1001,共4位比特,最高位的1,实际上在除法的每次XOR时,都要消掉,所
以这个1可不做参考,后3位001才是最重要的!001有3位,所以得到的余数也是3位,因为最后一次除
法XOR时,最高位消掉了。所以CRC就是3位比特的。 
CRC是3比特,表示它的宽度W=3。也就是说,原始数据后面要加上W=3比特的0进行扩展! 
生成项的最低位也必须是1,这是规定的。 
生成项1001,就等效于g(x)=x2+1 
生成项也可以倒过来写,即颠倒过来,写成1001,这里倒过来的值是一样的。 
 
再如CRC32的生成项是: 
1 0000 0100 1100 0001 0001 1101 1011 0111  (33个比特) 
即g(x)= x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 
颠倒过来,就可以写成1110 1101 1011 1000 1000 0011 0010 0000 1 
一般生成项简写时不写最高位的1,故生成项是0x04C11DB7,颠倒后的生成项是0xEDB88320 
CRC32的生成项是33比特,最高位是消掉的,即CRC值是32比特(4个字节),即宽度W=32,就是说,
在计算前,原始数据后面要先扩展W=32个比特0,即4个0x00字节。 
 
注意:我看到网上CRC32的POLY有0x04C10DB7这个值的,它和正规的POLY值不同,需要注意! 
 
颠倒过来,即是镜像,为什么要颠倒,后述。

拿运 CRC CCITT-16 为例子,行下面的代码,CRC_acc = 0xFFFF;CRC_input[0] = 0x63; 返回校验值CRC.

  1. unsigned short UpdateCRC(unsigned short CRC_acc, unsigned char *CRC_input, unsigned int len)
  2. {
  3. unsigned char i,k = 0;
  4. #define POLY_ 0x1021
  5. while (len--)
  6. {
  7. CRC_acc = CRC_acc ^ (CRC_input[k++] << 8);
  8. printf("CRC_input:%d : %s\n", CRC_input[0], itoa(CRC_input[0], binbuf, 2));
  9. printf("CRC_input:%x :%s\n", CRC_acc, itoa(CRC_acc, binbuf, 2));
  10. printf("POLY_ :%x :%s\n\n", POLY_, itoa(POLY_, binbuf, 2));
  11. printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
  12. for (i = 0; i < 8; i++)
  13. {
  14. if ((CRC_acc & 0x8000) == 0x8000)
  15. {
  16. printf("chushi :%x :%s\n", 0, itoa(CRC_acc, binbuf, 2));
  17. CRC_acc = CRC_acc << 1;
  18. printf("you yi :%x :%s\n", 0, itoa(CRC_acc, binbuf, 2));
  19. CRC_acc ^= POLY_;
  20. printf("POLY_1 :%x :%s\n\n", 0, itoa(CRC_acc, binbuf, 2));
  21. }
  22. else
  23. {
  24. printf("chushi :%x :%s\n", 0, itoa(CRC_acc, binbuf, 2));
  25. CRC_acc = CRC_acc << 1;
  26. printf("POLY_0 :%x :%s\n\n", 0, itoa(CRC_acc, binbuf, 2));
  27. }
  28. }
  29. }
  30. return CRC_acc;
  31. }

  

CRC16 的生成及校验原理的更多相关文章

  1. 最详细易懂的CRC-16校验原理(附源程序)(转)

    最详细易懂的CRC-16校验原理(附源程序) from:http://www.openhw.org/chudonganjin/blog/12-08/230184_515e6.html 最详细易懂的CR ...

  2. 最详细易懂的CRC-16校验原理(附源程序)

    from:http://www.openhw.org/chudonganjin/blog/12-08/230184_515e6.html 最详细易懂的CRC-16校验原理(附源程序) 1.循环校验码( ...

  3. CRC-16校验原理

    最详细易懂的CRC-16校验原理(附源程序) 1.循环校验码(CRC码): 是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定. 2.生成CRC码的基本原理: 任意一 ...

  4. CRC码计算及校验原理的最通俗诠释

    5.3.2 循环冗余校验检错方案 奇偶校验码(PCC)只能校验一位错误,本节所要介绍的循环冗余校验码(CRC)的检错能力更强,可以检出多位错误. 1. CRC校验原理      CRC校验原理看起来比 ...

  5. CRC校验原理

    此文为转载文,原作者博客传送门 CRC校验原理 CRC校验原理看起来比较复杂,好难懂,因为大多数书上基本上是以二进制的多项式形式来说明的.其实很简单的问题,其根本思想就是先在要发送的帧后面附加一个数( ...

  6. ECC校验原理以及在Nand Flash中的应用

         本篇文章主要介绍ECC基本原理以及在Nand Flash中的应用,本文记录自己对ECC校验原理的理解和学习. ECC介绍      ECC,全称为Error Correcting Code, ...

  7. CRC 校验原理及步骤

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

  8. CRC校验原理及步骤

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

  9. Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle

    Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle 1. 主键1 2. uniq  index2 3.  ...

随机推荐

  1. 关于系统弹出错误:429 , ActiveX 部件不能创建对象 的解决方法

    例如:win7 win10的系统,有时候运行某些软件会出现:429 , ActiveX 部件不能创建对象 的情况. 提示: "运行时错误'429': ActiveX 部件不能创建对象&quo ...

  2. Python_day1 Learning record

    Python Day1 Learning record(python第一天学习记录) 一.ptyhon安装 windows .下载安装包 https://www.python.org/download ...

  3. oraclesql语句笔记

    1. ORA-00947:Not enough values 原因:values没有写足够的值与select()中的字段对应 2.查看一张表中共有多少个字段 select count(*) from ...

  4. Beta冲刺 5

    前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/10129059.html 作业博客:https://edu.cnblogs.com/campus ...

  5. [Java concurrent][Collections]

    同步容器类 同步容器类包括Vector和Hashtable,二者是早期JDK的一部分.以及一些在JDK1.2中添加的可以由Collections.synchronizedXxx等工厂方法创建的. 这些 ...

  6. OpenGL 3D旋转的木箱

    学习自: https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/#3d 0,首先添加glm ...

  7. nginx——优化 Nginx access 日志

    1. 配置日志切割 #!/bin/bash savepath_log='/usr/local/clogs' nglogs='/usr/local/nginx/logs' mkdir -p $savep ...

  8. socket网络编程-----I/O复用之select函数

    #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/soc ...

  9. SSRF漏洞浅析

    大部分web应用都提供了从其他的服务器上获取数据的功能,如使用用户指定的URL,web应用可以获取图片,下载文件,读取文件内容等.如果服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与 ...

  10. openSUSE安装Qt5

    找了很多资料发现没一个好用又简单的. 终于在wiki.qt.io上找到了一个! 安装方法如下: 1下载安装包,我建议最好下载离线包.下载链接http://download.qt.io/archive/ ...