CRC校验算法详解及代码实现[通俗易懂]

CRC校验算法详解及代码实现一、 CRC校验算法前置知识在学习CRC校验算法之前,先复习一下CRC会涉及的主要几个主要的算法。异或异或,就是不同为1,相同为0,运算符号是^。0^0=00^1=11^1=01^0=1异或运算存在如下几个规律,需要了解。0^x=x 即0异或任何数等于任何数1^x=~x 即1异或任何数等于任何数取反…

大家好,又见面了,我是你们的朋友全栈君。

CRC校验算法详解及代码实现

一、 CRC校验算法前置知识

在学习CRC校验算法之前,先复习一下CRC会涉及的主要几个主要的算法。

1. 异或

异或,就是不同为1,相同为0,运算符号是^。
0^0 = 0
0^1 = 1
1^1 = 0
1^0 = 1

异或运算存在如下几个规律,需要了解。

  1. 0^x = x 即0 异或任何数等于任何数
  2. 1^x = ~x 即1异或任何数等于任何数取反
  3. x^x = 0 即任何数与自己异或,结果为0
  4. a ^ b = b ^ a 交换律
  5. a ^ (b ^ c) = (a ^ b) ^c 结合律

2. 模2加法

模2加法相对于普通的算术加法,主要的区别在模2加法,不做进位处理。具体结果如下。
0+0 = 0
0+1 = 1
1+1 = 0
1+0 = 1
我们发现模2加法的计算结果,同异或运算结果一模一样。进一步推演,我们会发现,异或运算的5个规律,同样适合于模2加法。这里,就不在一一列举了。

3. 模2减法

模2减法相对于普通的算术减法,主要的区别在模2减法,不做借位处理。具体结果如下。
0-0 = 0
0-1 = 1
1-1 = 0
1-0 = 1
我们发现模2减法的计算结果,同模2加法,以及异或的运算结果一模一样。进一步推演,我们会发现,异或运算的5个规律,同样适合于模2减法。这里,就不在一一列举了。

4. 模2除法

模2除法相对于普通的算术除法,主要的区别在模2除法,它既不向上位借位,也不比较除数和被除数的相同位数值的大小,只要以相同位数进行相除即可。下面是一个模2除法的示例。被除数是101001000,除数1101。
在这里插入图片描述
选取被除数前面的1010模2除以除数1101,因最高为是1,所以,得到商1,余数通过1010和1101的模2减法获得,根据前面的模2减法运算的介绍,其运算结果和异或运算一模一样。因此,得到余数:1010 ^ 1101 = 0111。去掉最高位的0,得到111,再将上面被除数的下一位,即0拿下来,得到1110。1110模2除以1101,得到商1,余数1110 ^ 1101 = 0011。除掉最高为的0,拿下被除数的下一位,即1,得到0111。此时,因为最高位是0,所以得到商0,余数0111 ^ 0000 = 0111。去掉最高为的,再和被除数的下一位结合,继续模2除法。按照上图依次计算,可以得到最终的商110101,余数001。
从上面的示例,我们看到一个规律:每循环一次模2计算,如果得到的被除数最高位是0,则一轮循环使用0000作为除数。如果得到的被除数最高位是1,则下一轮循环除数使用1101。这样可以保证每一轮循环被除数都能向右平移一位,直到循环到被除数最后一位。
根据之前章节中介绍的异或运算的几条规律,我们可以很容易得到一个结论,如果我们将模2除法的余数和被除数的最后几位(与余数的位数一下,本例中就是3)异或之后,得到一个新的数,这个新的数,再使用模2除法除以除数1101,即可整除,即余数为0。

二、 CRC校验算法及实现

CRC校验的根本思想就是先在要发送的帧后面附加一个数(这个就是用来校验的校验码),生成一个新帧发送给接收端。当然,这个附加的数不是随意的,它要使所生成的新帧能与发送端和接收端共同选定的某个特定数值整除(注意,这里不是直接采用二进制除法,而是采用 “模2除法”)。因为在发送端发送数据帧之前就已通过附加一个数,做了“去余”处理(也就已经能整除了),所以结果应该是没有余数。如果有余数,则表明该帧在传输过程中出现了差错。

具体来说,CRC校验原理就是以下几个步骤:

  1. 先选择(可以随机选择,也可按标准选择,具体在后面介绍)一个用于在接收端进行校验时,对接收的帧进行“模2除法”运算的除数(是二进制比较特串,通常是以多项方式表示,所以CRC又称多项式编码方法,这个多项式也称之为“生成多项式”)。
  2. 看所选定的除数二进制位数(假设为k位),然后在要发送的数据帧(假设为m位)后面加上k-1位“0”,然后以这个加了k-1个“0“的新帧(一共是m+k-1位)以“模2除法”方式除以上面这个除数,所得到的余数(也是二进制的比特串)就是该帧的CRC校验码,也称之为FCS(帧校验序列)。但要注意的是,余数的位数一定要是比除数位数只能少一位,哪怕前面位是0,甚至是全为0(附带好整除时)也都不能省略。
  3. 再把这个校验码附加在原数据帧(就是m位的帧,注意不是在后面形成的m+k-1位的帧)后面,构建一个新帧发送到接收端,最后在接收端再把这个新帧以“模2除法”方式除以前面选择的除数,如果没有余数,则表明该帧在传输过程中没出错,否则出现了差错。

从上面可以看出,CRC校验中有两个关键点:
一是要预先确定一个发送端和接收端都用来作为除数的二进制比特串(或多项式);
二是把原始帧并追加k-1位”0″后得到的新帧与上面选定的除数进行模2除法运算,计算出CRC。
前者可以随机选择,也可按国际上通行的标准选择,但最高位和最低位必须均为“1”,如在IBM的SDLC(同步数据链路控制)规程中使用的CRC-16(也就是这个除数一共是17位,这样的话,得到的余数的位数就是17-1=16)生成多项式g(x)= x16 + x15 + x2 +1(对应二进制比特串为:11000000000000101)。

理论上,使用上述CRC校验步骤的第二步计算CRC的时候,需要将所有的二进制序列(包括后加的k-1个0)作为一个整体按照第一章节中模2除法的方法,除以选定的除数。但是,考虑模2除法中实际使用的运算其实一直都是按位异或,结合异或运算的结合律,我们逐个bit逐个bit地将作为被除数的二进制序列的每个bit依次引入,也可以逐个字节逐个字节的引入。下面是通过逐个字节引入方式计算CRC的代码实现,假设校准使用的多项式为x8+x5+x4+1 (对应二进制为: 0b100110001,对应HEX值为0x131)。

/*************************************** *@DESCRIPTION: -- CRC8计算, * *@Parameters: -- *data_ptr:待计算CRC8的数据 * len:待计算CRC8数据的长度 * *@Return: --无 ****************************************/	
unsigned char calculate_crc8(unsigned char *data_ptr, unsigned char len)
{ 
   
  unsigned int i;
  unsigned char j;
  unsigned char crc = 0x00;
  for (i=0; i<len; i++)
  { 
   
    crc ^= *data_ptr;
    data_ptr++;
    for (j=8; j>0; j--)
    { 
   
      if (crc & 0x80)
      { 
   
        crc <<= 1;
        crc ^= 0x31;    // 0x131最高位1去掉,只与低8bit的0x31异或即可。
      } // if (crc & 0x80)
      else
      { 
    
        crc <<= 1;
      /*当最高bit为0时,则crc与0按位异或,仍为crc,所以,没有语句"crc ^= 0x31;”。*/
      } // else
    } // for (j=8; j>0; j--)
  } // for (i=0; i<len; i++)
  return crc;
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/126045.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • SpringBoot实现文件上传接口[通俗易懂]

    SpringBoot实现文件上传接口[通俗易懂]摘要公司都是采用SpringBoot作为项目框架,其实SpringBoot和SSM框架很接近,基本上只是将SSM的一些配置项修改为自动配置或者简单的注解配置就可以了,建议不了解的SpringBoot的朋友们可以了解一下,上手很快,其实文件上传框架根本没有多大关系。我只是顺便帮SpringBoot打个广告罢了。正题需求:需要实现一个文件上传的web接口。1、先实现一个Controll…

  • 大数据分析应用的机遇与挑战「建议收藏」

    大数据分析应用的机遇与挑战「建议收藏」随着信息技能的发展,互联网家当的进步,计算机数据处理能力的快速增长,电子商务的日新月异及各种社交媒体的传播扩散,各种信息无时无刻不在影响着我们的生活。我们每时每刻都在自觉或者不自觉得与数据打交道,成为数据的记录者与传播者。海量数据的处理,以及如何利用大数据营销,给我们提出了更多的挑战。在这个人人都高喊“大数据时代”的今天,数据似乎被提到一个前所未有的高度。无论是个人还是企业,无论是网络营销还是线…

  • idea如何创建一个javaweb项目_Java创建一个新项目

    idea如何创建一个javaweb项目_Java创建一个新项目Idea创建JavaWeb项目步骤:1、打开IntellijIdeaIDE,然后点击CreateNewProject2、左侧选择JavaEnterprise,右侧选择WebApplication3、这里输入项目名字为firstdemo,然后点击Finish完成。生成如下的项目结构:项目配置:1、在web/WEB-INF下创建两个文件夹classes和lib,classes用来存放编译后输出的classes文件,lib用于存放第三方jar包。..

  • Access数据库多表联合查询

    Access数据库多表联合查询Access数据库多表联合查询1、Access数据库多表联合查询,每次连接之前须将连接符前面的内容放在括号里面,示例如下:      select表a.字段1,表b.字段1,表c.字段1,表d.字段1from((表ainnerjoin表bon表a.字段=表b.字段)innerjoin表con表c.字段=表a.字段)innerjoin表don表a.

  • MPI 之 点对点通信的一个实例

    MPI 之 点对点通信的一个实例目标:通过MPI实现100次点对点通信,并计算平均每次的通信时间。代码如下:/**点对点通信100次,计算平均通信时间,并观察传输数据量大小和传输时间关系数据量变化采用动态内存方式从4kb增加到400M,每次增大400kb**/#include&lt;stdio.h&gt;//标准输入输出头文件#include&lt;stdlib.h&gt;//标准库#incl…

  • linux的进程调度指的是系统对进程调用_Linux进程调度实验

    linux的进程调度指的是系统对进程调用_Linux进程调度实验进程状态进程调度就是让进程从一种状态切换到另一种状态。Linux中进程的主要状态如下,值状态缩写含义0TASK_RUNNINGR正在运行或可运行1TASK_INTERRUPTIBLES可中断的休眠2TASK_UNINTERRUPTIBLED不可中断的休眠4__TASK_STOPPEDT停止状态,当进程接收到SIGSTOP等signal信息8__TASK_TRACEDt跟踪状态,进程被debugge…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号