<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>CRC on Rancho&#39;s Notes</title>
    <link>https://fan-pengfei.top/tags/crc/</link>
    <description>Recent content in CRC on Rancho&#39;s Notes</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sat, 08 Jan 2022 02:21:29 +0000</lastBuildDate>
    <atom:link href="https://fan-pengfei.top/tags/crc/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>CRC校验原理</title>
      <link>https://fan-pengfei.top/posts/crc%E6%A0%A1%E9%AA%8C%E5%8E%9F%E7%90%86/</link>
      <pubDate>Sat, 08 Jan 2022 02:21:29 +0000</pubDate>
      <guid>https://fan-pengfei.top/posts/crc%E6%A0%A1%E9%AA%8C%E5%8E%9F%E7%90%86/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;之前经常用CRC校验，今天解释一下其原理；&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;简单介绍&#34;&gt;简单介绍：&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Cyclic Redundancy Check循环冗余检验，是基于数据计算一组效验码，用于核对数据传输过程中是否被更改或传输错误。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;循环冗余校验检错方案（CRC）：&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CRC校验原理看起来比较复杂，好难懂，因为大多数书上基本上是以二进制的多项式形式来说明的。其实很简单的问题，其根本思想就是先在要发送的帧后面附加一个数（这个就是用来校验的校验码，但要注意，这里的数也是二进制序列的，下同），生成一个新帧发送给接收端。当然，这个附加的数不是随意的，它  要使所生成的新帧能与发送端和接收端共同选定的某个特定数整除（注意，这里不是直接采用二进制除法，而是采用一种称之为“模2除法”）。到达接收端后，再把接收到的新帧除以（同样采用“模2除法”）这个选定的除数。因为在发送端发送数据帧之前就已通过附加一个数，做了“去余”处理（也就已经能整除了），所以结果应该是没有余数。如果有余数，则表明该帧在传输过程中出现了差错。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;【说明】&lt;/strong&gt;：“模2除法”与“算术除法”类似，但它既不向上位借位，也不比较除数和被除数的相同位数值的大小，只要以相同位数进行相除即可。模2加法运算为：1+1=0，0+1=1，0+0=0，无进位，也无借位；模2减法6运算为：1-1=0，0-1=1，1-0=1，0-0=0，也无进位，无借位。相当于二进制中的逻辑异或运算。也就是比较后，两者对应位相同则结果为“0”，不同则结果为“1”。如100101除以1110，结果得到商为11，余数为1，如图5-9左图所示。如11×11=101，如右图所示。&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;最通俗的CRC校验原理剖析_深入理解计算机网络&#34; loading=&#34;lazy&#34; src=&#34;https://fan-pengfei.top/posts/crc%E6%A0%A1%E9%AA%8C%E5%8E%9F%E7%90%86/img-1.jpg&#34;&gt;
&lt;img alt=&#34;最通俗的CRC校验原理剖析_CRC_02&#34; loading=&#34;lazy&#34; src=&#34;https://fan-pengfei.top/posts/crc%E6%A0%A1%E9%AA%8C%E5%8E%9F%E7%90%86/img-2.jpg&#34;&gt;&lt;/p&gt;
&lt;p&gt;“模2除法”和“模2乘法”示例&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;具体来说，CRC校验原理就是以下几个步骤：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;先选择（可以随机选择，也可按标准选择，具体在后面介绍）一个用于在接收端进行校验时，对接收的帧进行除法运算的除数（是二进制比较特串，通常是以多项方式表示，所以CRC又称多项式编码方法，这个多项式也称之为“生成多项式”）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;看所选定的除数二进制位数（假设为k位），然后在要发送的数据帧（假设为m位）后面加上k-1位“0”，然后以这个加了k-1个“0“的新帧（一共是m+k-1位）以“模2除法”方式除以上面这个除数，所得到的余数（也是二进制的比特串）就是该帧的CRC校验码，也称之为FCS（帧校验序列）。但要注意的是，余数的位数一定要是比除数位数只能少一位，哪怕前面位是0，甚至是全为0（附带好整除时）也都不能省略。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;再把这个校验码附加在原数据帧（就是m位的帧，注意不是在后面形成的m+k-1位的帧）后面，构建一个新帧发送到接收端；最后在接收端再把这个新帧以“模2除法”方式除以前面选择的除数，如果没有余数，则表明该帧在传输过程中没出错，否则出现了差错。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;通过以上介绍，大家一定可以理解CRC校验的原理，并且不再认为很复杂吧。  从上面可以看出，CRC校验中有两个关键点：一是要预先确定一个发送端和接收端都用来作为除数的二进制比特串（或多项式）；二是把原始帧与上面选定的除进行二进制除法运算，计算出FCS。前者可以随机选择，也可按国际上通行的标准选择，但最高位和最低位必须均为“1”，如在IBM的SDLC（同步数据链路控制）规程中使用的CRC-16（也就是这个除数一共是17位）生成多项式g（x）= x^16 + x^15 + x^2 +1（对应二进制比特串为：11000000000000101）；而在ISO HDLC（高级数据链路控制）规程、ITU的SDLC、X.25、V.34、V.41、V.42等中使用CCITT-16生成多项式g（x）= x^16+ x^15 + x^5 +1（对应二进制比特串为：11000000000100001）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;CRC校验码的计算示例&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;由以上分析可知，既然除数是随机，或者按标准选定的，所以CRC校验的关键是如何求出余数，也就是校验码（CRC校验码）。下面以一个例子来具体说明整个过程。现假设选择的CRC生成多项式为G（X） = X^4 + X^3 + 1，要求出二进制序列10110011的CRC校验码。下面是具体的计算过程：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;首先把生成多项式转换成二进制数，由G（X） = X^4+ X^3 + 1可以知道，它一共是5位（总位数等于最高位的幂次加1，即4+1=5），然后根据多项式各项的含义（多项式只列出二进制值为1的位，也就是这个二进制的第4位、第3位、第0位的二进制均为1，其它位均为0）很快就可得到它的二进制比特串为11001。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;因为生成多项式的位数为5，根据前面的介绍，得知CRC校验码的位数为4（校验码的位数比生成多项式的位数少1）。因为原数据帧10110011，在它后面再加4个0，得到101100110000，然后把这个数以“模2除法”方式除以生成多项式，得到的余数（即CRC码）为0100，如图所示。注意参考前面介绍的“模2除法”运算法则。
&lt;img alt=&#34;最通俗的CRC校验原理剖析_王达_03&#34; loading=&#34;lazy&#34; src=&#34;https://fan-pengfei.top/posts/crc%E6%A0%A1%E9%AA%8C%E5%8E%9F%E7%90%86/img-3.jpg&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CRC校验码计算示例&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;把上步计算得到的CRC校验0100替换原始帧101100110000后面的四个“0”，得到新帧101100110100。再把这个新帧发送到接收端。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;当以上新帧到达接收端后，接收端会把这个新帧再用上面选定的除数11001以“模2除法”方式去除，验证余数是否为0，如果为0，则证明该帧数据在传输过程中没有出现差错，否则出现了差错。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;通过以上CRC校验原理的剖析和CRC校验码的计算示例的介绍，大家应该对这种看似很复杂的CRC校验原理和计算方法应该比较清楚了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;算法原理&#34;&gt;算法原理：&lt;/h2&gt;
&lt;p&gt;假设数据传输过程中需要发送15位的二进制信息g=101001110100001，这串二进制码可表示为代数多项式g(x) = x^14 + x^12 + x^9 + x^8 + x^7 + x^5+ 1，其中g中第k位的值，对应g(x)中x^k 的系数。将g(x)乘以x^m，既将g后加m个0，然后除以m阶多项式h(x)，得到的(m-1)阶余项r(x)对应的二进制码r就是CRC编码。&lt;/p&gt;
&lt;p&gt;h(x)可以自由选择或者使用国际通行标准，一般按照h(x)的阶数m，将CRC算法称为CRC-m，比如CRC-32、CRC-64等。国际通行标准可以参看&lt;a href=&#34;http://en.wikipedia.org/wiki/Cyclic_redundancy_check&#34;&gt;标准&lt;/a&gt;；&lt;/p&gt;
&lt;p&gt;g(x)和h(x)的除运算，可以通过g和h做xor（异或）运算。比如将11001与10101做xor运算：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;img&#34; loading=&#34;lazy&#34; src=&#34;https://fan-pengfei.top/posts/crc%E6%A0%A1%E9%AA%8C%E5%8E%9F%E7%90%86/img-4.gif&#34;&gt;&lt;/p&gt;
&lt;p&gt;明白了xor运算法则后，举一个例子使用CRC-8算法求101001110100001的效验码。CRC-8标准的h(x) = x^8 + x^7 + x^6 + x^4 + x^2 + 1，既h是9位的二进制串111010101。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
