精华内容
下载资源
问答
  • 2021-05-23 09:27:34

    众所周知,不可能有永远都不会出错的人,同样也不可能有永远不出错的计算机,永远不出错的数据。

    人有知错能改的觉悟,计算机也有,不过计算机没有人类聪明,只能通过一个特定的方法进行自我改正,这就是校验码存在的必要了。

    一般用得比较多的校验码有奇偶校验码,CRC循环冗余校验码,海明校验码等。

    这里只介绍用的最多的CRC循环冗余校验码。

    何为校验码

    校验码是通过一种计算方法,发出端在原始数据的尾部添加若干数据;然后接收端通过计算得出数据有无错误,并且能把错误的数据还原成正确的数据。

    例如,原始数据为1010,我们通过在其尾部添加若干数据,比如101,则数据变成了1010101,将这个新的数据发送出去;假如在发送过程中出现错误,数据变成了1110101,则接收端能根据1110101还原成原始正确的数据1010。

    CRC循环冗余校验码的特点

    CRC码是基于模2运算建立编码规律的校验码(模2运算可以简单的理解为异或运算)。

    编码方法:

    1.将原始数据用一个多项式M(x) = A*X^(n-1)+B*X^(n-2)+…+N*X^(1)+P*X^(0)

    比如说原始数据是1010,则表示为M(x) = 1*X^(3)+0*X^(2)+1*X^(1)+0*X^(0)

    2.将原始数据左移k位,得到M(X)*X^k,形成了n+k位信息。

    上面的1010,左移3位,得到1010 000

    3.用多项式M(X)*X^k 除以(或者说异或)一个特定的生成多项式G(X),所得余数则为需要拼接到原始数据尾部的CRC校验码。

    例:

    已知原始数据为1100,生成多项式G(X)=1011,则求算CRC码的过程如下:

    已知  :M(X) = 1100 = X^3+X^2      (n=4)

    由        G(X) = 1011 = X^3+X^1+1

    得        k+1 = n = 4

    得       k=3,需要左移3位

    故得     M(X)*X^3 = 1100 000

    (M(X)*X^3) / G(X)计算过程:

    1100 000                M(X)*X^3

    1011                      G(X)

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

    111 0                     余数,高位0省去;然后余数左移1位,继续异或G(X)

    101 1                  G(X)

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

    10 10                  左移1位,继续异或G(X)

    10 11

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

    10                  由于k=3,而算到这里我们已经对余数移位2次,还需1次

    则最后算出来的结果是010,则原始数据变成了1100 010,最后三位是CRC码。

    很容易发现,如果我们需要算k位码,则G(X)的位数应该是K+1.

    由于最后的数据变成了7位,而有效数据还是4位,故上述的1100 010码又叫做(7,4)码,对应的还有(7,3)码,(7,6)码等。

    CRC码的译码规则和纠错方法

    还是刚刚的例子,我们用最后得出的数据除以G(X),发现其余数为0,这个就是正确的数据。

    我们尝试改动其中一位,比如说第2位,得到:1000 010,我们用这个数除以G(X),发现余数为111,余数不为0,则说明数据有错了!

    下面给出每个位出错对应的余数:

    序号

    N1  N2  N3  N4  N5  N6  N7

    余数

    出错位

    正确

    1    1    0    0    0    1    0

    000

    错误

    1    1    0    0    0    1    1

    001

    7

    错误

    1    1    0    0    0    0    0

    010

    6

    错误

    1    1    0    0    1    1    0

    100

    5

    错误

    1    1    0    1    0    1    0

    011

    4

    错误

    1    1    1    0    0    1    0

    110

    3

    错误

    1    0    0    0    0    1    0

    111

    2

    错误

    0    1    0    0    0    1    0

    101

    1

    假如我们现在收到一个错误的信息是1000 010,通过计算可以得出余数是111,但是如何得知是第几位出错了?

    我们试着对余数111补0后继续除下去,发现下一次的余数变成了101,继续下去,又变成了001,以后依次出现为010,100,011。。。反复循环,这就是“循环码”名字的由来。

    这样,假如N2出现错误,则出现了不为0的余数后,一方面对余数补0继续模2除,另一方面将被检测的校验码字循环左移,当余数为101(即数据的首位为0)时,通过异或门可以将其纠正后在下一次移位时送回N2。这样当移满一个循环后,就得到一个纠正后的数据了。

    最后给出几个标准

    在上面的计算中可以发现,G(X)的作用非常重要,生成CRC码和译码都需要它。值得指出的是,并不是随便一个(K+1)位数据都可以作为生成多项式,它要满足的条件:

    1.任何一位出错,都不能使余数为0,这是非常显然的;

    2.不同位发生错误后,余数不能相同;

    3.对余数继续模2除,应使余数循环。

    为了方便起见,也为了标准化工作,现在一般用的生成多项式有以下几个:

    CRC-16 = X16 + X15 + X2 + X0           美国二进制同步系统中采用

    CRC-CCITT = X16 + X12 + X5 + X0        由欧洲CCITT 推荐

    CRC-32 = X32 + X26 + X23 + X22 + X16 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + X0

    下面贴出生成CRC码的代码

    #include #include

    using namespacestd;#define CRC_16 0x18005

    //CRC-16 = X16 + X15 + X2 + X0

    #define CRC_CCITT 0x11021

    //CRC-CCITT = X16 + X12 + X5 + X0

    #define CRC_32 0x104C11DB7

    //CRC-32 = X32 + X26 + X23 + X22 + X16 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + X0

    #define CHECK_CODE 0x8000

    //check_code = x15,判断被除数位数>=16//check_code是为了每次做异或运算时保证位数是足够的

    unsignedlong table[256];void build_16(unsigned longpoly)

    {

    unsignedlongx;

    unsignedlongt;/*这里是将原始数据直接写入到t中

    for (unsigned long i=0; i<256; i++)

    {

    x = i << 8;

    t = 0;

    for (unsigned long j = 0; j < 8; j++)

    {

    if ( (x ^ t) & CHECK_CODE)

    t = (t << 1) ^ poly;

    else

    t <<= 1;

    x <<= 1;

    }

    table[i] = ( unsigned long ) t;

    }*/

    //下面的是把余数和原始数据分开的写法//原始数据只有8位

    for (int i=0; i<256; i++)

    {

    x= i<<8;//只移8位是为了位数对齐,因为下面的运算都是低位对齐的

    for (int j=0; j<8; j++)

    {if (x&CHECK_CODE)

    {

    x<<= 1;

    x= x^poly;

    }else x <<= 1;

    }

    table[i]= (i<<16)+x;

    }

    }void build_32(unsigned longpoly)

    {

    unsignedlongx;for (unsigned long i=0; i<256; i++)

    {

    x= i<<24;for (unsigned long j=0; j<8; j++)

    {if (x & 0x80000000) //判断位数是否足够,32位

    {

    x<<= 1;

    x= x^poly;

    }else x <<= 1;

    }

    table[i]= (i<<32)+x;

    }

    }intmain()

    {

    build_16(CRC_16);

    build_16(CRC_CCITT);

    build_32(CRC_32);for (int i=0; i<256; i++)

    {if (i % 10 == 0)

    cout<

    printf("%lx", table[i]);

    }return 0;

    }

    更多相关内容
  • CRC原理 计算方式如下图所示,若除数为n位,待校验的数据为k位,则现在待校验的数据后面添加n-1个0,然后再和除数进行模2除法,所谓模2除法,其实就是将竖式运算中的减法改为异或运算。 C代码实现 #include &...

    CRC原理

    计算方式如下图所示,若除数为n位,待校验的数据为k位,则先在待校验的数据后面添加n-1个0,然后再和除数进行模2除法,所谓模2除法,其实就是将竖式运算中的减法改为异或运算。

    è¿éåå¾çæè¿°

     C代码实现

    #include <iostream>
    #include<stdio.h>
    using namespace std;
    
    int P[4]={1,0,1,1};
    
    
    void XOR(int a[4],int b[4]){
        for(int i=0;i<4;i++){
            if(a[i]==1){
                if(b[i]==1){
                    a[i]=0;
                }
                else{
                    a[i]=1;
                }
            }
            else{
                if(b[i]==0){
                    a[i]=0;
                }
                else{
                    a[i]=1;
                }
            }
        }
    }
    
    void print_result(int a[4]){
       printf("result:\n");
       for(int i=3;i>=0;i--){
          printf("%d ",a[i]);
       }
       printf("\n");
    }
    
    void crc(int X[9],int FCS[3]){
       int result[4];
       int t=4;
       for(int i=0;i<4;i++){
           result[i]=X[9-(4-i)];
       }
       XOR(result,P);
       print_result(result);
       while(1){
           printf("t=%d,shift\n",t);
           for(int i=4-1;i>=1;i--){
              result[i]=result[i-1];
           }
           result[0]=X[t--];
           if(result[3]==1){
              XOR(result,P);
           }
           else{
              ;//和0000异或,即恒等运算
           }
           //print result
           print_result(result);
           if(t<0){
              for(int i=0;i<3;i++){
                 FCS[i]=result[i];
              }
              break;
           }
       }
    }
    
    int main()
    {
        int X[9]={0,0,0,1,0,0,1,0,1};                   //结果应为001
        int Y[9]={0,0,0,0,1,1,0,1,1};                   //结果应为111
        int FCS[3];
        crc(Y,FCS);
        //
        cout<<"final result=";
        cout <<FCS[2]<<" "<<FCS[1]<<" "<<FCS[0]<<endl;
        return 0;
    }
    

    展开全文
  • CRC循环冗余校验算法C语言实现 CRC循环冗余校验算法C语言实现
  • 描述一、CRC简介循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及...

    描述

    一、CRC简介

    循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。

    在数据传输过程中,无论传输系统的设计再怎么完美,差错总会存在,这种差错可能会导致在链路上传输的一个或者多个帧被破坏(出现比特差错,0变为1,或者1变为0),从而接受方接收到错误的数据。为尽量提高接受方收到数据的正确率,在接收方接收数据之前需要对数据进行差错检测,当且仅当检测的结果为正确时接收方才真正收下数据。检测的方式有多种,常见的有奇偶校验、因特网校验和循环冗余校验等。

    二、CRC硬件计算过程

    1.设置CRC寄存器,并给其赋值FFFF(hex)。

    2.将数据的第一个8-bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC寄存器。

    3.CRC寄存器向右移一位,MSB补零,移出并检查LSB。

    4.如果LSB为0,重复第三步;若LSB为1,CRC寄存器与多项式码相异或。

    注意:该步检查LSB应该是右移前的LSB,即第3步前的LSB。

    5.重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。

    6.重复第2至第5步直到所有数据全部处理完成。7.最终CRC寄存器的内容即为CRC值。

    三、循环冗余校验码(CRC)的基本原理

    在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码又叫(N,K)码。对于一个给定的(N,K)码,可以证明存在一个最高次幂为N-K=R的多项式G(x)。根据G(x)可以生成K位信息的校验码,而G(x)叫做这个CRC码的生成多项式。

    校验码的具体生成过程为:假设发送信息用信息多项式C(X)表示,将C(x)左移R位,则可表示成C(x)*2R,这样C(x)的右边就会空出R位,这就是校验码的位置。通过C(x)*2R除以生成多项式G(x)得到的余数就是校验码。

    原理思维导图总结:

    38673fb08f4078b247571e9216f62e66.png

    123352e9e60ae8ecc6c46faa14fbd4d6.png

    四、通信与网络中常用的CRC

    在数据通信与网络中,通常k相当大,由一千甚至数千数据位构成一帧,而后采用CRC码产生r位的校验位。它只能检测出错误,而不能纠正错误。一般取r=16,标准的16位生成多项式有CRC-16=x16+x15+x2+1 和 CRC-CCITT=x16+x15+x2+1。

    一般情况下,r位生成多项式产生的CRC码可检测出所有的双错、奇数位错和突发长度小于等于r的突发错以及(1-2-(r-1))的突发长度为r+1的突发错和(1-2-r)的突发长度大于r+1的突发错。例如,对上述r=16的情况,就能检测出所有突发长度小于等于16的突发错以及99.997%的突发长度为17的突发错和99.998%的突发长度大于17的突发错。所以CRC码的检错能力还是很强的。这里,突发错误是指几乎是连续发生的一串错,突发长度就是指从出错的第一位到出错的最后一位的长度(但是,中间并不一定每一位都错)。

    【例1】某循环冗余码(CRC)的生成多项式 G(x)=x3+x2+1,用此生成多项式产生的冗余位,加在信息位后形成 CRC 码。若发送信息位 1111 和 1100 则它的 CRC 码分别为_A_和_B_。由于某种原因,使接收端收到了按某种规律可判断为出错的 CRC 码,例如码字_C_、_D_、和_E_。(1998年试题11)

    供选择的答案:

    A:① lllll00 ② 1111101 ③ 1111110 ④ 1111111

    B:① 1100100 ② 1100101 ③ 1100110 ④ 1100111

    C~E:① 0000000 ② 0001100 ③ 0010111 ⑤ 1000110 ⑥ 1001111 ⑦ 1010001 ⑧ 1011000

    解:

    A:G(x)=1101,C(x)=1111 C(x)*23÷G(x)=1111000÷1101=1011余111

    得到的CRC码为1111111

    B:G(x)=1101,C(x)=1100 C(x)*23÷G(x)=1100000÷1101=1001余101

    得到的CRC码为1100101

    C~E:

    分别用G(x)=1101对①~⑧ 作模2除: ① 0000000÷1101 余000 ② 1111101÷1101 余001

    ③ 0010111÷1101 余000 ④ 0011010÷1101 余000 ⑤ 1000110÷1101 余000

    ⑥ 1001111÷1101 余100 ⑦ 1010001÷1101 余000 ⑧ 1011000÷1101 余100

    所以_C_、_D_和_E_的答案是②、⑥、⑧

    【例2】计算机中常用的一种检错码是CRC,即 _A_ 码。在进行编码过程中要使用 _B_ 运算。假设使用的生成多项式是 G(X)=X4+X3+X+1, 原始报文为11001010101,则编码后的报文为 _C_ 。CRC码 _D_ 的说法是正确的。

    在无线电通信中常采用它规定码字长为7位.并且其中总有且仅有3个“1”。这种码的编码效率为_E_。

    供选择的答案:

    A:① 水平垂直奇偶校验 ② 循环求和 ③ 循环冗余 ④正比率

    B:① 模2除法 ②定点二进制除法 ③二-十进制除法 ④循环移位法

    C:① 1100101010111 ② 110010101010011 ③ 110010101011100 ④ 110010101010101

    D:① 可纠正一位差错 ②可检测所有偶数位错

    ③ 可检测所有小于校验位长度的突发错 ④可检测所有小于、等于校验位长度的突发错

    E:① 3/7 ② 4/7 ③ log23/log27 ④ (log235)/7

    解:从前面有关CRC的论述中可得出: A:③ 循环冗余 B:① 模2除法

    C:G(x)=11011,C(x)=11001010101,C(x)*24÷G(x)=110010101010000÷11011 余0011

    得到的CRC码为② 110010101010011

    D:从前面有关通信与网络中常用的CRC的论述中可得出:④ 可检测所有小于、等于校验位长度的突发错

    E:定比码又叫定重码,是奇偶校验的推广。在定比码中,奇数或偶数的性质保持不变,然而附加一种限制,每个字中1的总数是固定的。随用途之不同,定比码要求的附加校验位可能多于一个,但较之单一的奇偶校验将增加更多的检错能力。

    所谓7中取3定比码,就是整个码字长度为7位,其中1的位数固定为3。所有128个7位代码(0000000~1111111)中只有1的位数固定为3的才是其合法码字。可以用求组合的公式求出其合法码字数为:C73=7!/(3!*(7-3)!)=7*6*5/(1*2*3)=35

    编码效率=合法码字所需位数/码字总位数=(log235)/7

    而对于CRC的实现有两种方式,分别为多项式和查表法。

    打开APP阅读更多精彩内容

    点击阅读全文

    展开全文
  • 常用的校验方式有奇偶校验、异或校验、累加和校验(可以看我之前的一篇文章累加和校验算法(CheckSum算法))、循环冗余校验CRC校验)等等。 奇偶校验、异或校验、累加和校验都比较简单,且易于实现,但是检错能力...

    一、概述

    现在的产品开发过程中,无论是数据的储存还是传输,都需要确保数据的准确性,所以就需要在数据帧后面附加一串校验码,方便接收方使用校验码校验接收到的数据是否是正确的。

    常用的校验方式有奇偶校验、异或校验、累加和校验(可以看我之前的一篇文章累加和校验算法(CheckSum算法))、循环冗余校验(CRC校验)等等。

    奇偶校验、异或校验、累加和校验都比较简单,且易于实现,但是检错能力也一般,而本文的主角CRC校验,则大大提高了数据的检错能力。(对比文章看这篇《奇偶校验 累加和校验 CRC校验》

    讲CRC校验的文章很多,也有非常多的好文章,本文只是将这些文章总结,用自己的理解再阐述一遍,再次感谢各位大佬优质的文章。

    CRC校验有很多的参数模型,尤其是有很多标准模型的存在,这些标准模型经过理论计算,大大提高校验检错的能力,所以推荐使用标准模型,由于有大量的教程和网上资源,参考后实现起来也比较简单,同时也利于不同部门间的沟通和定下标准。
    本文就是采用CRC-16/MODBUS参数模型,该模型就被各行各业大量使用

    二、CRC的基本原理

    网上有看到一篇讲解CRC原理的文章非常不错的文章:循环冗余检验 (CRC) 算法原理
    文章讲解了CRC校验的基本原理,讲的很清楚,尤其是查表法的原理,需要静下来心来看几遍才能理解透彻。
    如果还不懂,还可以看看这篇:最通俗的CRC校验原理剖析

    CRC的校验的结果不仅由选择的多项式决定,还包括其他各种参数,下面就是需要注意的参数:(来自CRC在线计算工具http://www.ip33.com/crc.html
    在这里插入图片描述
    这篇文章里面有详细地介绍了这些参数的讲解:CRC校验原理及其C语言实现

    三、CRC-16/MODBUS的介绍以及实现

    modbus是美国的modicon公司开发的一种报文传输协议,1979年该公司成为施耐德公司的一部分。modbus协议在工业控制中得到了广泛的应用,它已经成为一种通用的工业标准,该协议支持rs-232、rs-422、rs-485和以太网设备。不同厂商生产的控制设备通过modbus协议可以连成通信网络,进行集中监控。许多工控产品,例如plc、变频器、人机界面、dcs和自动化仪表等,都在广泛地使用modbus协议。

    而CRC-16/MODBUS作为modbus的数据校验方式,正成为比较通用的CRC检验的参数模型。

    CRCCRC-16/MODBUS C语言实现代码可以看这一篇文章:【CRC笔记】CRC-16 MODBUS C语言实现】

    CRC-16/MODBUS C语言的实现一般有直接计算法和查表法,直接计算法省存储耗时间,而查表法使用空间区换时间,校验过程耗时少但占用存储空间大。在平时的产品开发过程中,我们更看重时间,且查表法占用的存储一般是我们可以接受的,所以查表法的使用更加普遍。

    3.1、直接计算法的实现

    计算步骤为(摘抄自https://www.cnblogs.com/jungle1989/p/6372527.html)

    (1).预置 16 位寄存器为十六进制 FFFF(即全为 1) ,称此寄存器为 CRC 寄存器;
    (2).把第一个 8 位数据与 16 位 CRC 寄存器的低位相异或,把结果放于 CRC 寄存器;
    (3).检测相异或后的CRC寄存器的最低位,
    若最低位为1:CRC寄存器先右移1位,再与多项式A001H进行异或;
    若为0,则CRC寄存器右移1位,无需与多项式进行异或。
    (4).重复步骤 3 ,直到右移 8 次,这样整个 8 位数据全部进行了处理;
    (5).重复步骤 2 到步骤4,进行下一个 8 位数据的处理;
    (6).最后得到的 CRC 寄存器即为 CRC 码。

    根据上面的步骤,得到其C语言的代码实现为(摘抄自https://blog.csdn.net/u012028275/article/details/112066723,个人添加注释)

    //直接计算法计算crc
    unsigned short do_crc(unsigned char *ptr, int len)
    {
        unsigned int i;
        unsigned short crc = 0xFFFF;  //crc16位寄存器初始值
    
        while(len--)
        {
            crc ^= *ptr++;
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xA001; //多项式 POLY(0x8005)的高低位交换值,这是由于其模型的一些参数决定的
                else
                    crc = (crc >> 1);
            }
        }
    
        return crc;
    }
    

    3.2、查表法实现

    查表法确实是一种比较优秀的方法。实在佩服那些推导出来的大佬们,其原理的实现可以看这篇文章《循环冗余检验 (CRC) 算法原理》
    其实现其实是直接计算法的优化版,将一个字节的校验(8个位的校验)用查表一个操作来实现,大大减少了其运行时间。
    其C语言的代码实现如下所示(摘抄自https://blog.csdn.net/u012028275/article/details/112066723,个人添加注释)

    /* CRC余式表 */
    const unsigned int crc_table[256] = {
        0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
        0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
        0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
        0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
        0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
        0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
        0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
        0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
        0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
        0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
        0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
        0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
        0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
        0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
        0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
        0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
        0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
        0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
        0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
        0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
        0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
        0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
        0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
        0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
        0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
        0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
        0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
        0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
        0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
        0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
        0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
        0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
    };
    
    //查表法计算crc
    unsigned short do_crc_table(unsigned char *ptr, int len)
    {
        unsigned short crc = 0xFFFF;
        
        while(len--) 
        {
            crc = (crc >> 8) ^ crc_table[(crc ^ *ptr++) & 0xff]; //原理参考直接计算法
        }
        
        return (crc);
    }
    

    3.3、CRC 余式表的获取(C语言代码输出)

    一定有人好奇,上述的余式表是如何获取的呢?下面就使用C语言来输出这个表格。
    (注:本节的内容针对CRCCRC-16/MODBUS,别的参数模型需要根据具体协议修改)

    • 先获取一个单个字节在CRC 余式表对应的数据:(代码是不是很熟悉,其实就是直接计算法计算单个字节的那一部分代码)

      uint16_t byte_crc_get(uint8_t value)
      {
          uint8_t i;
          uint16_t crc = value;
          /* 数据往右移了8位,需要计算8次 */
          for (i=8; i>0; --i)
          { 
              if (crc & 1)  /* 判断最高位是否为1 */
              {
                  crc = (crc >> 1) ^ 0xA001;    
              }
              else
              {
                  crc = (crc >> 1);
              }
          }
          return crc;
      }
      
    • 获取所有字节数据对应的数据(一共256个),组成表格

      void  create_crc_table(void)
      {
          uint16_t i;
          uint16_t j;
      
          for (i=0; i<=0xFF; i++)
          {
              if (0 == (i%16))
                  printf("\n");
      
              j = i&0xFF;
              printf("0x%.4x, ", byte_crc_get (j));  /*依次计算每个字节的crc校验值*/
          }
      }
      
    • 最后在main函数中调用 create_crc_table()即可输出余式表,之后复制即可使用。
      在这里插入图片描述

    四、参考文章

    展开全文
  • 循环冗余校验CRC)——C语言

    万次阅读 多人点赞 2019-03-20 19:40:37
    CRC目前是在数据通信和计算机网络中应用最广泛的一种校验编码方式。它的原理十分简单但非常使用,具体内容可自行百度,下面主要讲一下我的代码的算法: 先来一组名字解释: Gx:生成码,这个是可以人为设定的,它...
  • CRC 校验算法示例: ...描 述: CRC16 循环冗余校验算法。 参 数 一: *puchMsg:需要校验的字符串指针 参 数 二: usDataLen:要校验的字符串长度 返 回 值: 返回 CRC16 校验码 ************************************.
  • 关于循环冗余码的定义,可以百度:http://baike.baidu.com/view/575295.htm#sub575295计算余数的二进制除法第一步,要在数据位(被除数)后边补 0 , 0 的个数比除数(生成多项式)少一位。第二步,做除法,从被除数的头五...
  • CRC循环校验介绍&C语言编程实现

    千次阅读 2020-04-13 12:10:50
    一、CRC循环校验码 1、理论解释: (1) 预先确定的多项式G(X): Gx:生成码,这个是可以人为设定的,它就是CRC里面所谓的生成多项式对应的系数。 其中,Gx 的首位和最后一位的系数必须为1 (2) 信息码,待发送的...
  • 文章简单介绍了循环冗余校验 CRC的算法分析和程序实现
  • CRC冗余校验C语言实现

    千次阅读 2016-10-08 16:59:07
    CRC循环冗余校验:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。
  • CRC循环冗余校验详解

    2021-10-02 23:45:18
    CRC循环冗余校验详解简介CRC手动演算CRC的直观运算过程 简介 https://www.bilibili.com/video/BV1V4411Z7VA?from=search&seid=3373767585328853317&spm_id_from=333.337.0.0 这个视频里讲的很明了透彻,本...
  • 之前在做学校项目的时候用到了CRC 原理,但在网上查找的过程中,发现讲解CRC知识的资源很多,但是对新手比较友好的、讲的十分清楚的又很少,很多资料也不完善,读起来心中常常不由自主地奔腾过上千个“为什么”“为...
  • 计算CRC冗余校验码(32)

    2017-02-17 14:26:37
    计算CRC 校验码 计算机网络
  • CRC校验原理及其C语言实现

    千次阅读 多人点赞 2020-09-27 22:00:06
    文章目录目录前言CRC算法简介CRC参数模型CRC计算CRC校验CRC计算的C语言实现CRC计算工具总结参考资料 目录 前言 CRC算法简介 CRC计算 CRC校验 CRC计算的C语言实现 CRC计算工具 总结 前言 最近的工作中,要实现对...
  • 循环冗余校验码(CRC)代码

    千次阅读 2020-05-24 22:27:19
    class CRC { public: void print_16(int sum)//输出对应的十六进制值 { if(sum<9) cout<<sum; else if(sum == 10) cout<<"A"; else if(sum == 11) cout<<"B"; else if(sum == ...
  • 现在此说明下什么是CRC循环冗余校验 英文名称为Cyclical Redundancy Check,简称CRC,它是利用除法及余数的原理来作错误侦测(Error Detecting)的。实际应用时,发送装置计算出CRC值并随数据一同发送给接收装置,...
  • CRC循环冗余校验码如何纠错
  • CRC循环冗余校验的matlab仿真程序

    热门讨论 2009-03-18 23:39:47
    CRC循环冗余编码的编译码过程,在matlab下的仿真程序
  • 验证网址: http://www.ip33.com/crc.html CRC-16/CCITT-FALSE验证 需要校验的数据:abc 数据的十六进制:61 62 63 ...将校验结果添加到校验的数据后面:61 62 63 51 4A,重新计算校验结果为0000. 校验完成 CRC-16/XMOD
  • 循环冗余校验CRC算法实现和求出碰撞值循环冗余校验CRC算法实现和求出碰撞值答:八位的碰撞一共有八个10001101 101010011110 101010101011 101010111000 101011000001 101011010010 101011100111 101011110100 ...
  • http://blog.csdn.net/liyuanbhu/article/details/7882789前言CRC校验(循环冗余校验)是数据通讯中最常采用的校验方式。在嵌入式软件开发中,经常要用到CRC 算法对各种数据进行校验。因此,掌握基本的CRC算法应是...
  • linux C累加和校验和CRC循环冗余校验的实验报告 摘要 在计算机中,当数据由发送方传至接收方时,需要进行数据校验。数据校验是为了保证数据的完整性而进行的一种验证操作。通常用一种指定的算法对原始数据计算出一个...
  • Cyclic Redundancy Check循环冗余检验,是基于数据计算一组效验码,用于核对数据传输过程中是否被更改或传输错误。完整的CRC-32标准所包含的内容:引用Name : "CRC-32"Width : 32Poly : 04C11DB7Initial value : ...
  • CRC循环校验C语言标准版实验程序

    千次阅读 2019-05-15 17:34:21
    本来已经写过一篇相关的文章,但总觉得跟书本上定义的实现算法不一样很不爽,所以按照书本上的定义,...首先是算法——完全按照教材规定的计算信息码、冗余码的方式编写测试的,如果不清楚请先自行百度“crc校验”;...
  • CRC循环冗余校验

    2020-03-11 11:13:36
    文章目录写在前面多项式初始值C语言软件公式实现 写在前面 CRC是一种差错检测方式之一,可以有效解决设备之间数据传输期间数据出错的检测,基本原理是通过一个多项式与数据进行除法和取余的方式计算。 CRC的种类很...
  • 循环冗余校验-CRC

    2022-05-24 13:16:19
    CRC的全称为Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的线性分组码,编码和解码方法简单,检错和纠错能力强,在通信领域广泛地用于实现差错控制。实际上,除 数据通信外,CRC在其它很多领域也...
  • CRC校验C语言实现

    2022-02-18 10:44:50
    摘自:CRC校验原理及其C语言实现 地址:https://blog.csdn.net/whik1194/article/details/108837493?spm=1001.2014.3001.5502
  • 硬件CRC循环冗余检验

    2015-05-14 15:00:05
    基于stm32的硬件CRC循环冗余检验例程
  • 标准CRC-8验证 需要校验的数据:abc 数据的十六进制:61 62 63 参数模型:CRC-8 宽度:8 多项式表达式:x8+x2+x+1 多项式:07 初始值:00 结果异或值:00 输入数据反转:NO 输出数据反转:NO 校验结果:5F 将0E...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,637
精华内容 654
关键字:

crc循环冗余校验c语言