关于CRC效验

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于CRC效验相关的知识,希望对你有一定的参考价值。

谁能详细解释一下,很茫然完全不懂!

  为保证传输过程的正确性,需要对通信过程进行差错控制。差错控制最常用的方法是自动请求重发方式(ARQ)、向前纠错方式(FEC)和混合纠错(HEC)。在传输过程误码率比较低时,用FEC方式比较理想。在传输过程误码率较高时,采用FEC容易出现“乱纠”现象。HEC方式则是ARQ和FEC的结合。在许多数字通信中,广泛采用ARQ方式,此时的差错控制只需要检错功能。实现检错功能的差错控制方法很多,传统的有:奇偶校验、校验和检测、重复码校验、恒比码校验、行列冗余码校验等,这些方法都是增加数据的冗余量,将校验码和数据一起发送到接受端。接受端对接受到的数据进行相同校验,再将得到的校验码和接受到的校验码比较,如果二者一致则认为传输正确。但这些方法都有各自的缺点,误判的概率比较高。
  循环冗余校验CRC(Cyclic Redundancy Check)是由分组线性码的分支而来,其主要应用是二元码组。编码简单且误判概率很低,在通信系统中得到了广泛的应用。下面重点介绍了CRC校验的原理及其算法实现。

  CRC校验可以100%地检测出所有奇数个随机错误和长度小于等于k(k为g(x)的阶数)的突发错误。所以CRC的生成多项式的阶数越高,那么误判的概率就越小。

  CRC代码的一些基本概念和运算:

  CRC多项式:

  例:

  代码:1010111 对应的多项式为:X6+X4+X2+X+1

  多项式X5+X3+X2+X1+1对应的代码为101111

  CRC生成多项式:

  首位和最后一位必须是1。CRC生成多项式是给定的,在传输过程中不变,即发送和接收端生成码相同。

  一些常用的校验码为:

  CRC8=X8+X5+X4+1

  CRC-CCITT=X16+X12+X5+1

  CRC16=X16+X15+X5+1

  CRC12=X12+X11+X3+X2+1

  CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1

  CRC的运算本质是异或运算(模2除法)

  例:原信息码为1011001

  生成码为11001

  校验码计算过程

  ① 将信息码左移4位(生成码长-1);得到10110010000

  ② 异或运算

  10110010000

  11001

  01111010000(前面的数进行异或运算,后面的直接抄下来)

  11001

  0011110000(和生成码异或运算的必须从1开始)

  11001

  00111000

  11001

  001010

  这样得到的结果为1010,即为所需要的校验码,添加到信息码后,得到发送的代码为:

  10110011010

  我把上面的手算过程用c#写了一段程序,如下:

  using System;

  namespace mainClass
  
  public class mainProgress
  
  public static void Main()
  
  byte[] msg=1,0,1,1,0,0,1;//信息码
  byte[] gmsg=new byte[msg.Length+4];
  crc c = new crc();
  gmsg=c.code(msg);
  Console.Write("编码后字符串为:");
  for (int i = 0; i < gmsg.Length; i++)
  
  Console.Write("0", gmsg[i].ToString());
  
  Console.Write("\n");
  byte[] gmsg1= 1, 0, 1, 1, 0, 1, 1 ;//接收到的代码
  bool r = c.det(gmsg1);
  if (r)
  
  Console.WriteLine("传输正确");
  
  else
   Console.WriteLine("传输错误");
  
  

  public class crc//CRC编码类
  
  private byte[] g = 1,1,0,0,1;//生成码
  public byte[] code(byte[] msg)//编码
  
  byte[] gmsg=new byte[g.Length+msg.Length-1];
  msg.CopyTo(gmsg, 0);//
  for (int i = 0; i < msg.Length; i++)//完成异或运算,即模2除法
  
  if (gmsg[i] == 1)
  
  for (int j = 0; j < g.Length; j++)
  
  if (gmsg[i + j] == g[j])
  gmsg[i + j] = 0;
  else
  gmsg[i + j] = 1;
  
  
  
  msg.CopyTo(gmsg, 0);
  return gmsg;
  
  private bool f=true;

  //接收端检测
  public bool det(byte[] gmsg)
  
  for (int i = 0; i < gmsg.Length - g.Length+1; i++)
  
  if(gmsg[i]==0)
  continue;
  for (int j = 0; j < g.Length; j++)
  
  if (gmsg[i + j] == g[j])
  gmsg[i + j] = 0;
  else
  gmsg[i + j] = 1;
  
  
  for (int i = 0; i < gmsg.Length; i++)
  
  if (gmsg[i] == 1)
  f = false;
  
  return f;
  

  
  
参考技术A 1、循环校验码(CRC码):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。
2、生成CRC码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。
3、CRC码集选择的原则:若设码字长度为N,信息字段为K位,校验字段为R位(N=K+R),则对于CRC码集中的任一码字,存在且仅存在一个R次多项式g(x),使得
V(x)=A(x)g(x)=xRm(x)+r(x);
其中: m(x)为K次信息多项式, r(x)为R-1次校验多项式,
g(x)称为生成多项式:
g(x)=g0+g1x+ g2x2+...+g(R-1)x(R-1)+gRxR
发送方通过指定的g(x)产生CRC码字,接收方则通过该g(x)来验证收到的CRC码字。
4、CRC校验码软件生成方法:
借助于多项式除法,其余数为校验字段。
例如:信息字段代码为: 1011001;对应m(x)=x6+x4+x3+1
假设生成多项式为:g(x)=x4+x3+1;则对应g(x)的代码为: 11001
x4m(x)=x10+x8+x7+x4 对应的代码记为:10110010000;
采用多项式除法: 得余数为: 1111 (即校验字段为:1111)
发送方:发出的传输字段为: 1 0 1 1 0 0 1 1111
信息字段 校验字段
接收方:使用相同的生成码进行校验:接收到的字段/生成码(二进制除法)
如果能够除尽,则正确,
给出余数(1111)的计算步骤:
除法没有数学上的含义,而是采用计算机的模二除法,即,除数和被除数做异或运算
1011001
1100100
=111101
111101
110010
= 1111
参考技术B 一篇通俗易懂的关于CRC的文章
https://zhuanlan.zhihu.com/p/81294341

关于CRC基础的几个问题

【中文标题】关于CRC基础的几个问题【英文标题】:A few questions about CRC basics 【发布时间】:2016-10-19 20:55:33 【问题描述】:

我是一名电子工程师,我发现从纯数学角度考虑 CRC 并不重要。但是,我有以下问题:

    为什么我们在计算 CRC 时要在消息中添加 n 个零,如果 n 是生成多项式的次数?我在模2长除法以及CRC的硬件实现中看到了这一点

    为什么我们希望生成多项式能被 (x+1) 整除?

    为什么我们希望生成多项式不能被 x 整除?

【问题讨论】:

【参考方案1】:
    我们在计算 n 位 CRC 时添加 n 零,因为在将 CRC 附加到消息并发送整体时(电信中的常见做法): 这允许接收端处理 CRC 的位,就像消息的其余部分一样,从而为任何无差错传输产生已知的剩余部分。当消息的结尾由遵循 CRC(一种常见做法)的东西指示时,这尤其有用;在接收端,它保存了一个n 位缓冲区,而在发送端,它几乎没有增加复杂性(x(n) 的额外项减少为一个与门,在 CRC 传输期间将消息位强制为零,n在传输 CRC 时执行额外的缩减步骤)。 在数学上,发送的 CRC 是 (M(x) * x^n) mod P(x) = R(x)(可能在某个常数范围内,或者/或者在 M(x) 的开头添加了一些规定的位,对应于 CRC 寄存器的初始化),并且在接收端计算 CRC是M(x)R(x) 的串联,即(M(x) * x^n + R(x)) mod P(x),它为零(或称常数)。 它确保影响消息结尾和连续 CRC 的错误突发从多项式选择所提供的完整保护级别中受益。特别是,如果我们将C(x) 计算为M(x) mod P(x),则翻转M(x) 的最后一位和C(x) 的最后一位将不会被检测到,而大多数用于错误检测的多项式确保检测到任何两位错误最大邮件大小。 通常的做法是让用于错误检测的 CRC 多项式可以被x+1 整除,因为这样可以确保检测到任何影响奇数位的错误。然而,这种做法并不普遍,它有时会阻止为更好的一些有用定义选择更好的多项式,包括最大化消息的长度,以便始终检测到 m 错误(假设没有同步丢失),对于某些组合mn。特别是,如果我们希望能够检测到可能的最长消息的任何 2 位错误(这将是 2n-1 位,包括 n-bit CRC),我们需要多项式是原始的,因此不可约,因此(对于n>1)不能被x+1整除。 普遍的做法是让用于错误检测的 CRC 多项式不能被 x 整除,否则生成的最后一位 CRC 将是恒定的,并且无助于检测消息其余部分中的错误+CRC .

【讨论】:

很好的答案。 +1。我只想补充一点,添加 n 零是 CRC 定义的一部分,但几乎从来不是实现的一部分。可以并且几乎总是实施软件或硬件中的 CRC 以避免那些额外的 n 步骤。对于 3,我会说它是真正通用的。如果多项式没有 1 项,则不是 CRC。 @Mark Adler:合并了您的 cmets。我猜你就是来自 Adler-32 的 Mark Adler,值得称赞! hmmmm 我需要更多地考虑答案 2。顺便说一下,2 中的“它防止多项式不可约”是什么意思。为什么我们需要不可约多项式? @quantum231:修正了我关于 2 的论点,这在某些时候使用不可约多项式的理由是不正确的。我现在至少给出一个很好的理由:这样多项式就可以是原始的,从而最大化检测到所有 2 位错误的消息长度。

以上是关于关于CRC效验的主要内容,如果未能解决你的问题,请参考以下文章

我要用C语言编写CRC16效验码。通过输入一个串然后计算出CRC16效验码。例如:输入010600001388计算得到849C

计算机网络CRC检验中为啥选择16或32位效验码,效率最高?

MD5、SHA1、CRC32是啥;作用是啥?

关于CRC的应用和总结

关于CRC基础的几个问题

关于python实现CRC32Mpeg2的应用和总结