精华内容
下载资源
问答
  • 1.CRC-16/MODBUS(最通用) 2.CRC-16/CCITT-FALSE 支持以上CRC校验计算方式(分查表法和计算法),原代码可执行,能正确输出结果。需要的朋友可以直接 引用到自己项目中。谢谢支持。
  • CRC 校验算法原理到FPGA实现代码。里面包括CRC检验的实现文档,Verilog HDL的实现代码,MATLAB仿真验证程序等,Testbench完整。可完美运行。
  • matlab CRC校验代码

    2019-03-28 09:10:09
    matlab CRC校验代码,亲自编写,支持16位校验,参照C代码编写,可用。
  • 实现CRC校验码的生成以及码块分割(依据协议3GPP 36.212)
  • CRC校验码Verilog程序

    2018-01-13 12:06:48
    算法可以根据自己需要调整测试,非常好用,主要在于不用查表,直接得出计算结果,计算占用资源少
  • 详述CRC校验码(附代码

    千次阅读 2021-08-26 00:15:28
    关注+星标公众号,不错过精彩内容来源| 一口LinuxCRC校验应用比较广泛,通常在通信领域用的比较多,即便是自定义通信协议,也可以添加CRC校验码,使其通信更加可靠。今天就来进一步描述...

    关注+星标公众,不错过精彩内容

    来源 | 一口Linux

    CRC校验应用比较广泛,通常在通信领域用的比较多,即便是自定义通信协议,也可以添加CRC校验码,使其通信更加可靠。

    今天就来进一步描述CRC校验码。

    一、CRC概念

    1. 什么是CRC?

    CRC(Cyclic Redundancy Checksum)是一种纠错技术,代表循环冗余校验和。

    数据通信领域中最常用的一种差错校验码,其信息字段和校验字段长度可以任意指定,但要求通信双方定义的CRC标准一致。主要用来检测或校验数据传输或者保存后可能出现的错误。它的使用方式可以说明如下图所示:

    在数据传输过程中,无论传输系统的设计再怎么完美,差错总会存在,这种差错可能会导致在链路上传输的一个或者多个帧被破坏(出现比特差错,0变为1,或者1变为0),从而接受方接收到错误的数据。

    为尽量提高接受方收到数据的正确率,在接收方接收数据之前需要对数据进行差错检测,当且仅当检测的结果为正确时接收方才真正收下数据。检测的方式有多种,常见的有奇偶校验因特网校验循环冗余校验等。

    2. 使用方法概述

    循环冗余校验是一种用于校验通信链路上数字传输准确性的计算方法(通过某种数学运算来建立数据位和校验位的约定关系的 )。

    发送方计算机使用某公式计算出被传送数据所含信息的一个值,并将此值 附在被传送数据后,接收方计算机则对同一数据进行 相同的计算,应该得到相同的结果。

    如果这两个 CRC结果不一致,则说明发送中出现了差错,接收方计算机可要求发送方计算机重新发送该数据。

    3. 应用广泛

    在诸多检错手段中,CRC是最著名的一种。CRC的全称是循环冗余校验,其特点是:检错能力强,开销小,易于用编码器及检测电路实现。从其检错能力来看,它所不能发现的错误的几率仅为0.0047%以下。

    从性能上和开销上考虑,均远远优于奇偶校验及算术和校验等方式。

    因而,在数据存储和数据通讯领域,CRC无处不在:著名的通讯协议X.25的FCS(帧检错序列)采用的是CRC-CCITT,WinRAR、NERO、ARJ、LHA等压缩工具软件采用的是CRC32,磁盘驱动器的读写采用了CRC16,通用的图像存储格式GIF、TIFF等也都用CRC作为检错手段。

    二、CRC名称的定义

    这里需要知道几个组成部分或者说计算概念:多项式公式、多项式简记式、数据宽度、初始值、结果异或值、输入值反转、输出值反转、参数模型。

    1、多项式公式

    对于CRC标准除数,一般使用多项式(或二项式)公式表示,如下图中除数11011(poly值为0x1b)的二项式为G(X)=X4+X3+X+1,X的指数就代表了该bit位上的数据为1,(最低位为0)。

    这里特别注意一下位数问题,除数的位数为二项式最高次幂+1(4+1=5),这个很重要。

    2、多项式简记式

    通过对CRC的基本了解我们知道,多项式的首尾必定为1,而这个1的位置在下一步计算一定为0,所以就把前面这个1给省略掉了,出现了一个叫简记式的东西,如上例中除数11011的简记式为1011,很多看过CRC高级语言源码的人会知道,对于CRC_16标准下G(X)=X16+X15+X2+1(16#18005)的poly值实际上是8005,这里使用的就是简记式。后面会对这个用法做一个说明。

    3、数据宽度

    数据宽度指的就是CRC校验码的长度(二进制位数),知道了CRC的运算概念和多项式,就可以理解这个概念了,CRC长度始终要比除数位数少1,与简记式长度是一致的。

    以上三个数据就是我们经常能够用到的基本数据

    4、初始值与结果异或值

    在一些标准中,规定了初始值,则数据在进行上述二项式运算之前,需要先将要计算的数据与初始值的最低字节进行异或,然后再与多项式进行计算。

    而在结果异或值不为零的情况下,则需要将计算得到的CRC结果值再与结果异或值进行一次异或计算,得到的最终值才是我们需要的CRC校验码。

    这里可以看出,初始值与结果值的位数要求与数据宽度一致。

    5、输入值反转与输出值反转

    输入值反转的意思是在计算之前先将二项式反转,然后再用得到的新值和数据进行计算。如对于G(X)=X16+X15+X2+1(16#18005),其正向值为1 1000 0000 0000 0101,反转值则为1010 0000 0000 0001 1

    输出值反转则是将最终得到的CRC结果反转。

    通常,输入值反转后的结果值也会是反转的,所以这两个选项一般是同向的,我们只有在在线CRC计算器中会看到自由选择正反转的情况存在。

    三、常见的CRC算法

    虽然CRC可以任意定义二项式、数据长度等,但没有一个统一的标准的话,就会让整个计算变得非常的麻烦。但实际上,不同的厂家经常采用不同的标准算法,这里列出了一些国际常用的模型表:

    名称多项式表示法应用举例
    CRC-8X8+X2+X+10X107
    CRC-12X12+X11+X3+X2+X+10X180Ftelecom systems
    CRC-16X16+X15+X2+10X18005Bisync, Modbus, USB, ANSI X3.28, SIA DC-07, many others; also known as CRC-16 and CRC-16-ANSI
    CRC-CCITTX16+X12+X5+10X11021ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS
    CRC-32X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X+10x104C11DB7ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS
    CRC-32CX32+X28+X27+X26+X25+X23+X22+X20+X19+X18+X14+X13+X11+X10+X9+X8+X6+10x11EDC6F41iSCSI, SCTP, G.hn payload, SSE4.2, Btrfs, ext4, Ceph

    四、CRC校验算法前置知识

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

    1. 异或

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

    0^0 = 0
    0^1 = 1
    1^1 = 0
    1^0 = 1
    

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

    0^x = x 即0 异或任何数等于任何数
    1^x = ~x 即1异或任何数等于任何数取反
    x^x = 0 即任何数与自己异或,结果为0
    a ^ b = b ^ a 交换律
    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除法,它既不向上位借位,也不比较除数和被除数的相同位数值的大小,只要以相同位数进行相除即可。

    五、CRC原理

    CRC原理:在K位信息码(目标发送数据)后再拼接R位校验码,使整个编码长度为N位,因此这种编码也叫(N,K)码。

    通俗的说,就是在需要发送的信息后面附加一个数(即校验码),生成一个新的发送数据发送给接收端。这个数据要求能够使生成的新数据被一个特定的数整除。这里的整除需要引入模 2除法的概念。

    那么,CRC校验的具体做法就是

    (1)选定一个标准除数(K位二进制数据串)

    (2)在要发送的数据(m位)后面加上K-1位0,然后将这个新数(M+K-1位)以模2除法的方式除以上面这个标准除数,所得到的余数也就是该数据的CRC校验码(注:余数必须比除数少且只少一位,不够就补0)

    (3)将这个校验码附在原m位数据后面,构成新的M+K-1位数据,发送给接收端。

    (4)接收端将接收到的数据除以标准除数,如果余数为0则认为数据正确。

    注意:CRC校验中有两个关键点:

    一是要预先确定一个发送端和接收端都用来作为除数的二进制比特串(或多项式);

    二是把原始帧与上面选定的除进行二进制除法运算,计算出FCS。

    前者可以随机选择,也可按国际上通行的标准选择,但最高位和最低位必须均为“1”

    六、循环冗余的计算

    实例:

    由于CRC-32、CRC-16、CCITT和CRC-4的编码过程基本一致,只有位数和生成多项式不一样,下面就举例,来说明CRC校验码生成过程。

    对于数据1110 0101(16#E5),以指定除数11011求它的CRC校验码,其过程如下:

    使用上面计算的校验和和消息数据,可以创建要传输的码字。

    有时候,我们需要填充checksum到制定的位置,这就涉及到字节序问题,建议用memcpy()进行拷贝。

    七、代码实现

    实现算法参考网络相关代码,进行整理并验证,可直接使用。crc.c

    /*  
     *一口Linux
     *2021.6.21
     *version: 1.0.0
    */
    #include "crc.h"
    #include <stdio.h>
    
    typedef enum {
     REF_4BIT = 4,
     REF_5BIT = 5,
     REF_6BIT = 6,
     REF_7BIT = 7,
     REF_8BIT = 8,
     REF_16BIT = 16,
     REF_32BIT = 32
    }REFLECTED_MODE;
    
    uint32_t ReflectedData(uint32_t data, REFLECTED_MODE mode)
    {
     data = ((data & 0xffff0000) >> 16) | ((data & 0x0000ffff) << 16);
     data = ((data & 0xff00ff00) >> 8) | ((data & 0x00ff00ff) << 8);
     data = ((data & 0xf0f0f0f0) >> 4) | ((data & 0x0f0f0f0f) << 4);
     data = ((data & 0xcccccccc) >> 2) | ((data & 0x33333333) << 2);
     data = ((data & 0xaaaaaaaa) >> 1) | ((data & 0x55555555) << 1);
    
     switch (mode)
     {
     case REF_32BIT:
      return data;
     case REF_16BIT:
      return (data >> 16) & 0xffff;
     case REF_8BIT:
      return (data >> 24) & 0xff;
     case REF_7BIT:
      return (data >> 25) & 0x7f;
     case REF_6BIT:
      return (data >> 26) & 0x7f;
     case REF_5BIT:
      return (data >> 27) & 0x1f;
     case REF_4BIT:
      return (data >> 28) & 0x0f;
     }
     return 0;
    }
    
    uint8_t CheckCrc4(uint8_t poly, uint8_t init, bool refIn, bool refOut, uint8_t xorOut,
     const uint8_t *buffer, uint32_t length)
    {
     uint8_t i;
     uint8_t crc;
    
     if (refIn == true)
     {
      crc = init;
      poly = ReflectedData(poly, REF_4BIT);
    
      while (length--)
      {
       crc ^= *buffer++;
       for (i = 0; i < 8; i++)
       {
        if (crc & 0x01)
        {
         crc >>= 1;
         crc ^= poly;
        }
        else
        {
         crc >>= 1;
        }
       }
      }
    
      return crc ^ xorOut;
     }
     else
     {
      crc = init << 4;
      poly <<= 4;
    
      while (length--)
      {
       crc ^= *buffer++;
       for (i = 0; i < 8; i++)
       {
        if (crc & 0x80)
        {
         crc <<= 1;
         crc ^= poly;
        }
        else
        {
         crc <<= 1;
        }
       }
      }
    
      return (crc >> 4) ^ xorOut;
     }
    }
    
    uint8_t CheckCrc5(uint8_t poly, uint8_t init, bool refIn, bool refOut, uint8_t xorOut,
     const uint8_t *buffer, uint32_t length)
    {
     uint8_t i;
     uint8_t crc;
    
     if (refIn == true)
     {
      crc = init;
      poly = ReflectedData(poly, REF_5BIT);
    
      while (length--)
      {
       crc ^= *buffer++;
       for (i = 0; i < 8; i++)
       {
        if (crc & 0x01)
        {
         crc >>= 1;
         crc ^= poly;
        }
        else
        {
         crc >>= 1;
        }
       }
      }
    
      return crc ^ xorOut;
     }
     else
     {
      crc = init << 3;
      poly <<= 3;
    
      while (length--)
      {
       crc ^= *buffer++;
       for (i = 0; i < 8; i++)
       {
        if (crc & 0x80)
        {
         crc <<= 1;
         crc ^= poly;
        }
        else
        {
         crc <<= 1;
        }
       }
      }
    
      return (crc >> 3) ^ xorOut;
     }
    }
    
    uint8_t CheckCrc6(uint8_t poly, uint8_t init, bool refIn, bool refOut, uint8_t xorOut,
     const uint8_t *buffer, uint32_t length)
    {
     uint8_t i;
     uint8_t crc;
    
     if (refIn == true)
     {
      crc = init;
      poly = ReflectedData(poly, REF_6BIT);
    
      while (length--)
      {
       crc ^= *buffer++;
       for (i = 0; i < 8; i++)
       {
        if (crc & 0x01)
        {
         crc >>= 1;
         crc ^= poly;
        }
        else
        {
         crc >>= 1;
        }
       }
      }
    
      return crc ^ xorOut;
     }
     else
     {
      crc = init << 2;
      poly <<= 2;
    
      while (length--)
      {
       crc ^= *buffer++;
       for (i = 0; i < 8; i++)
       {
        if (crc & 0x80)
        {
         crc <<= 1;
         crc ^= poly;
        }
        else
        {
         crc <<= 1;
        }
       }
      }
    
      return (crc >> 2) ^ xorOut;
     }
    }
    
    uint8_t CheckCrc7(uint8_t poly, uint8_t init, bool refIn, bool refOut, uint8_t xorOut,
     const uint8_t *buffer, uint32_t length)
    {
     uint8_t i;
     uint8_t crc;
    
     if (refIn == true)
     {
      crc = init;
      poly = ReflectedData(poly, REF_7BIT);
    
      while (length--)
      {
       crc ^= *buffer++;
       for (i = 0; i < 8; i++)
       {
        if (crc & 0x01)
        {
         crc >>= 1;
         crc ^= poly;
        }
        else
        {
         crc >>= 1;
        }
       }
      }
    
      return crc ^ xorOut;
     }
     else
     {
      crc = init << 1;
      poly <<= 1;
    
      while (length--)
      {
       crc ^= *buffer++;
       for (i = 0; i < 8; i++)
       {
        if (crc & 0x80)
        {
         crc <<= 1;
         crc ^= poly;
        }
        else
        {
         crc <<= 1;
        }
       }
      }
    
      return (crc >> 1) ^ xorOut;
     }
    }
    
    uint8_t CheckCrc8(uint8_t poly, uint8_t init, bool refIn, bool refOut, uint8_t xorOut,
     const uint8_t *buffer, uint32_t length)
    {
     uint32_t i = 0;
     uint8_t crc = init;
    
     while (length--)
     {
      if (refIn == true)
      {
       crc ^= ReflectedData(*buffer++, REF_8BIT);
      }
      else
      {
       crc ^= *buffer++;
      }
    
      for (i = 0; i < 8; i++)
      {
       if (crc & 0x80)
       {
        crc <<= 1;
        crc ^= poly;
       }
       else
       {
        crc <<= 1;
       }
      }
     }
    
     if (refOut == true)
     {
      crc = ReflectedData(crc, REF_8BIT);
     }
    
     return crc ^ xorOut;
    }
    
    uint16_t CheckCrc16(uint16_t poly, uint16_t init, bool refIn, bool refOut, uint16_t xorOut,
     const uint8_t *buffer, uint32_t length)
    {
     uint32_t i = 0;
     uint16_t crc = init;
    
     while (length--)
     {
      if (refIn == true)
      {
       crc ^= ReflectedData(*buffer++, REF_8BIT) << 8;
      }
      else
      {
       crc ^= (*buffer++) << 8;
      }
    
      for (i = 0; i < 8; i++)
      {
       if (crc & 0x8000)
       {
        crc <<= 1;
        crc ^= poly;
       }
       else
       {
        crc <<= 1;
       }
      }
     }
    
     if (refOut == true)
     {
      crc = ReflectedData(crc, REF_16BIT);
     }
    
     return crc ^ xorOut;
    }
    
    uint32_t CheckCrc32(uint32_t poly, uint32_t init, bool refIn, bool refOut, uint32_t xorOut,
     const uint8_t *buffer, uint32_t length)
    {
     uint32_t i = 0;
     uint32_t crc = init;
    
     while (length--)
     {
      if (refIn == true)
      {
       crc ^= ReflectedData(*buffer++, REF_8BIT) << 24;
      }
      else
      {
       crc ^= (*buffer++) << 24;
      }
    
      for (i = 0; i < 8; i++)
      {
       if (crc & 0x80000000)
       {
        crc <<= 1;
        crc ^= poly;
       }
       else
       {
        crc <<= 1;
       }
      }
     }
    
     if (refOut == true)
     {
      crc = ReflectedData(crc, REF_32BIT);
     }
    
     return crc ^ xorOut;
    }
    
    uint32_t CrcCheck(CRC_Type crcType, const uint8_t *buffer, uint32_t length)
    {
     switch (crcType.width)
     {
     case 4:
      return CheckCrc4(crcType.poly, crcType.init, crcType.refIn, crcType.refOut,
       crcType.xorOut, buffer, length);
     case 5:
      return CheckCrc5(crcType.poly, crcType.init, crcType.refIn, crcType.refOut,
       crcType.xorOut, buffer, length);
     case 6:
      return CheckCrc6(crcType.poly, crcType.init, crcType.refIn, crcType.refOut,
       crcType.xorOut, buffer, length);
     case 7:
      return CheckCrc7(crcType.poly, crcType.init, crcType.refIn, crcType.refOut,
       crcType.xorOut, buffer, length);
     case 8:
      return CheckCrc8(crcType.poly, crcType.init, crcType.refIn, crcType.refOut,
       crcType.xorOut, buffer, length);
     case 16:
      return CheckCrc16(crcType.poly, crcType.init, crcType.refIn, crcType.refOut,
       crcType.xorOut, buffer, length);
     case 32:
      return CheckCrc32(crcType.poly, crcType.init, crcType.refIn, crcType.refOut,
       crcType.xorOut, buffer, length);
     }
     return 0;
    }
    
    

    crc.h

    /*  
     *一口Linux
     *2021.6.21
     *version: 1.0.0
    */
    #ifndef __CRC_H__
    #define __CRC_H__
    
    #include <stdint.h>
    #include <stdbool.h>
    
    typedef struct {
     uint8_t width;
     uint32_t poly;
     uint32_t init;
     bool refIn;
     bool refOut;
     uint32_t xorOut;
    }CRC_Type;
    
    uint32_t CrcCheck(CRC_Type crcType, const uint8_t *buffer, uint32_t length);
    
    #endif
    

    main.c

    /*  
     *一口Linux
     *2021.6.21
     *version: 1.0.0
    */
    #include <stdio.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include "crc.h"
    
    #define LENGTH 8
    const uint8_t data[3][LENGTH] = {
     { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
     { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
     { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }};
    
    typedef struct {
     CRC_Type crcType;
     uint32_t result[3];
    }CRC_Test;
    
    CRC_Test crc4_ITU = { { 4, 0x03, 0x00, true, true, 0x00 }, { 0x0f, 0x0a, 0x0e } };
    CRC_Test crc5_EPC = { { 5, 0x09, 0x09, false, false, 0x00 }, { 0x00, 0x0c, 0x17 } };
    CRC_Test crc5_ITU = { { 5, 0x15, 0x00, true, true, 0x00 }, { 0x16, 0x0a, 0x17 } };
    CRC_Test crc5_USB = { { 5, 0x05, 0x1f, true, true, 0x1f }, { 0x10, 0x09, 0x17 } };
    CRC_Test crc6_ITU = { { 6, 0x03, 0x00, true, true, 0x00 }, { 0x1d, 0x30, 0x00 } };
    CRC_Test crc7_MMC = { { 7, 0x09, 0x00, false, false, 0x00 }, { 0x57, 0x30, 0x5b } };
    CRC_Test crc8 = { { 8, 0x07, 0x00, false, false, 0x00 }, { 0x3e, 0xe1, 0x36 } };
    CRC_Test crc8_ITU = { { 8, 0x07, 0x00, false, false, 0x55 }, { 0x6b, 0xb4, 0x63 } };
    CRC_Test crc8_ROHC = { { 8, 0x07, 0xff, true, true, 0x00 }, { 0x6b, 0x78, 0x93 } };
    CRC_Test crc8_MAXIM = { { 8, 0x31, 0x00, true, true, 0x00 }, { 0x83, 0x60, 0xa9 } };
    CRC_Test crc16_IBM = { { 16, 0x8005, 0x0000, true, true, 0x0000 }, { 0xc4f0, 0x2337, 0xa776 } };
    CRC_Test crc16_MAXIM = { { 16, 0x8005, 0x0000, true, true, 0xffff }, { 0x3b0f, 0xdcc8, 0x5889 } };
    CRC_Test crc16_USB = { { 16, 0x8005, 0xffff, true, true, 0xffff }, { 0x304f, 0xd788, 0x53c9 } };
    CRC_Test crc16_MODBUS = { { 16, 0x8005, 0xffff, true, true, 0x0000 }, { 0xcfb0, 0x2877, 0xac36 } };
    CRC_Test crc16_CCITT = { { 16, 0x1021, 0x0000, true, true, 0x0000 }, { 0xeea7, 0xfe7c, 0x7919 } };
    CRC_Test crc16_CCITT_FALSE = { { 16, 0x1021, 0xffff, false, false, 0x0000 }, { 0x4792, 0x13a7, 0xb546 } };
    CRC_Test crc16_X25 = { { 16, 0x1021, 0xffff, true, true, 0xffff }, { 0x6dd5, 0x7d0f, 0xfa6a } };
    CRC_Test crc16_XMODEM = { { 16, 0x1021, 0x0000, false, false, 0x0000 }, { 0x76ac, 0x2299, 0x8478 } };
    CRC_Test crc16_DNP = { { 16, 0x3D65, 0x0000, true, true, 0xffff }, { 0x7bda, 0x0535, 0x08c4 } };
    CRC_Test crc32 = { { 32, 0x04c11db7, 0xffffffff, true, true, 0xffffffff }, { 0x3fca88c5, 0xe0631a53, 0xa4051a26 } };
    CRC_Test crc32_MPEG2 = { { 32, 0x4c11db7, 0xffffffff, false, false, 0x00000000 }, { 0x14dbbdd8, 0x6509b4b6, 0xcb09d294 } };
    
    void CrcTest(CRC_Test crcTest)
    {
     uint32_t i;
     for (i = 0; i < 3; i++)
     {
      printf("%08x\t%08x\r\n", CrcCheck(crcTest.crcType, data[i], LENGTH), crcTest.result[i]);
     }
     printf("\r\n");
    }
    
    int main(void)
    {
     CrcTest(crc4_ITU);
     CrcTest(crc5_EPC);
     CrcTest(crc5_ITU);
     CrcTest(crc5_USB);
     CrcTest(crc6_ITU);
     CrcTest(crc7_MMC);
     CrcTest(crc8);
     CrcTest(crc8_ITU);
     CrcTest(crc8_ROHC);
     CrcTest(crc8_MAXIM);
     CrcTest(crc16_IBM);
     CrcTest(crc16_MAXIM);
     CrcTest(crc16_USB);
     CrcTest(crc16_MODBUS);
     CrcTest(crc16_CCITT);
     CrcTest(crc16_CCITT_FALSE);
     CrcTest(crc16_X25);
     CrcTest(crc16_XMODEM);
     CrcTest(crc16_DNP);
     CrcTest(crc32);
     CrcTest(crc32_MPEG2);
    
     return 0;
    }
    
    

    注意

    不同的CRC算法,对00H或FFH数据流的计算结果不一样,部分算法存在校验结果也为00H或FFH的情况(也就意味着存储空间处于初始化状态时:全0或全1,CRC校验反而是正确的),在应用中需要注意避免。

    ------------ END ------------


    ●嵌入式专栏精选教程

    ●精选汇总 | ST工具、下载编程工具

    ●精选汇总 | 嵌入式软件设计与开发

    ●精选汇总 | STM32、MCU、单片机

    迎关注我的公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。

    欢迎关注我的视频号:

    点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

    展开全文
  • 自己写的verilog代码 已经添加适当注释 可以说囊括了所有CRC算法。。。 自定义生成多项式 初始化异或值 输出异或值 校验位和每拍输入数据的位宽都是参数化设计 附带testbench测试文件 已经使用后仿真验证
  • C#实现CRC32校验码运算

    2018-12-03 11:20:30
    CRC32校验码计算,C#源代码,国标一致性文档,官方测试通过。
  • c语言中crc校验码的生成源代码,及二进制显示的一段代码
  • java实现CRC校验码

    2021-02-12 19:48:27
    这两天项目中要使用到CRC校验功能,网上大量的例子是针对c、delphi的例子,前期没有做过,理论上也欠缺很多知识,在这里对java如何实现我们想要的crc校验功能做一下自己的总结,以下内容有本分转自网上,希望对有...

    这两天项目中要使用到CRC校验功能,网上大量的例子是针对c、delphi的例子,前期没有做过,理论上也欠缺很多知识,在这里对java如何实现我们想要的crc校验功能做一下自己的总结,以下内容有本分转自网上,希望对有需要的朋友作能够参考一下。

    一、什么是CRC校验:

    CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。

    二、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码字。

    (对于细节性的知识朋友们可以在网上找到大量资料这里不再做重复说明) (以上来自网络转载)

    三、CRC校验码方式有哪些:

    1 byte checksum

    CRC-16

    CRC-16 (Modbus)

    CRC-16 (Sick)

    CRC-CCITT (XModem)

    CRC-CCITT (0xFFFF)

    CRC-CCITT (0x1D0F)

    CRC-CCITT (Kermit)

    CRC-DNP

    CRC-32

    对于以上方式来说结果可以生成为ASCII、HEX等方式

    四、JAVA实现CRC校验

    (1)这里对于CRC-CCITT四种方式进行梳理:

    public class CRC {

    /**

    * CRC-CCITT(Kermit)验证模式

    * @param str

    * @return

    */

    public String CRC_CCITT_Kermit(String str) {

    int j, b, rrrc, c, i;

    String tmpBalance;

    int k;

    rrrc = 0;

    tmpBalance = str;

    int tmpInt, CharInt;

    String tmpChar, tmpStr;

    tmpStr = "";

    int High;

    int Low;

    for (j = 1; j <= 3; j++) {

    if (Character.isDigit(tmpBalance.charAt(2 * j - 2))) {

    High = Integer.parseInt(tmpBalance.charAt(2 * j - 2) + "");

    } else {

    High = 0;

    }

    if (Character.isDigit(tmpBalance.charAt(2 * j - 1))) {

    Low = Integer.parseInt(tmpBalance.charAt(2 * j - 1) + "");

    } else {

    Low = 0;

    }

    High = (High & 0xff) << 4;

    High = High | Low;

    k = High;

    for (i = 1; i <= 8; i++) {

    c = rrrc & 1;

    rrrc = rrrc >> 1;

    if ((k & 1) != 0) {

    rrrc = rrrc | 0x8000;

    }

    if (c != 0) {

    rrrc = rrrc ^ 0x8408;

    }

    k = k >> 1;

    }

    }

    for (i = 1; i <= 16; i++) {

    c = rrrc & 1;

    rrrc = rrrc >> 1;

    if (c != 0) {

    rrrc = rrrc ^ 0x8408;

    }

    }

    c = rrrc >> 8;

    b = rrrc << 8;

    rrrc = c | b;

    tmpInt = rrrc;

    tmpStr = "";

    for (i = 1; i <= 4; i++) {

    tmpChar = "";

    CharInt = tmpInt % 16;

    if (CharInt > 9) {

    switch (CharInt) {

    case 10:

    tmpChar = "A";

    break;

    case 11:

    tmpChar = "B";

    break;

    case 12:

    tmpChar = "C";

    break;

    case 13:

    tmpChar = "D";

    break;

    case 14:

    tmpChar = "E";

    break;

    case 15:

    tmpChar = "F";

    break;

    }

    } else {

    tmpChar = Integer.toString(CharInt);

    }

    tmpInt = tmpInt / 16;

    tmpStr = tmpChar + tmpStr;

    }

    System.out.println("tmpStr:" + tmpStr);

    return tmpStr;

    }

    /**

    * CRC-CCITT(XModem)

    * CRC-CCITT(0xFFFF)

    * CRC-CCITT(0x1D0F)

    * 校验模式

    * @param flag< XModem(flag=1) 0xFFFF(flag=2) 0x1D0F(flag=3)>

    * @param str

    * @return

    */

    public String CRC_CCITT( int flag,String str) {

    int crc = 0x00; // initial value

    int polynomial = 0x1021;

    byte[] bytes=str.getBytes();

    switch(flag){

    case 1:

    crc=0x00;

    break;

    case 2:

    crc=0xFFFF;

    break;

    case 3:

    crc=0x1D0F;

    break;

    }

    for (int index = 0 ; index< bytes.length; index++) {

    byte b = bytes[index];

    for (int i = 0; i < 8; i++) {

    boolean bit = ((b >> (7-i) & 1) == 1);

    boolean c15 = ((crc >> 15 & 1) == 1);

    crc <<= 1;

    if (c15 ^ bit) crc ^= polynomial;

    }

    }

    crc &= 0xffff;

    str = Integer.toHexString(crc);

    return str;

    }

    分享到:

    18e900b8666ce6f233d25ec02f95ee59.png

    72dd548719f0ace4d5f9bca64e1d7715.png

    2011-03-17 08:30

    浏览 322

    评论

    展开全文
  • Verilog语言实现CRC校验

    2019-05-04 21:55:52
    功能:输入多个8bit数据,输出16bitCRC值,用的多项式是CRC8005,通过修改例程中的某字节(程序中有注明),可以实现CRC1021
  • js脚本实现CRC校验码

    热门讨论 2013-11-14 17:40:44
    CRC 校验 编码,使用js实现CRC编码
  • ModBus通讯,CRC校验码生成,Java版实现;ModBus,CRC,Java版实现
  • 循环冗余校验码(CRC)计算源代码合集,里面包含了各种编程语言(包括C,C++,单片机等)CRC代码实现
  • 网上的一般都是查表法,这是我按模2除法写的。 里面有2个函数: 1、带入需要计算的数据串与除数(最高位与最低位必须为1),得出CRC校验码,插入尾部 2、验证数据的完整性(验证携带8位CRC校验码数据的完整性)
  • 基于VS2010 C# Modbus_CRC16校验码计算
  • 错误检测的方法错误校验(CRC)域占用两个字节,包含了一个16位的二进制值。CRC值由传输设备计算出来,然后附加到数据帧上,接收设备在接收数据时重新计算CRC值,然后与接收到的CRC域中的值进行比较,如果这两个值不...

    错误检测的方法

    错误校验(CRC)域占用两个字节,包含了一个16位的二进制值。CRC值由传输设备计算出来,然后附加到数据帧上,接收设备在接收数据时重新计算CRC值,然后与接收到的CRC域中的值进行比较,如果这两个值不相等,就发生了错误。

    CRC运算时,首先将一个16位的寄存器预置为全1,然后连续把数据帧中的每个字节中的8位与该寄存器的当前值进行运算,仅仅每个字节的8个数据位参与生成CRC,起始位和终止位以及可能使用的奇偶位都不影响CRC。在生成CRC时,每个字节的8位与寄存器中的内容进行异或,然后将结果向低位移位,高位则用“0”补充,最低位(LSB)移出并检测,如果是1,该寄存器就与一个预设的固定值(0A001H)进行一次异或运算,如果最低位为0,不作任何处理。

    上述处理重复进行,直到执行完了8次移位操作,当最后一位(第8位)移完以后,下一个8位字节与寄存器的当前值进行异或运算,同样进行上述的另一个8次移位异或操作,当数据帧中的所有字节都作了处理,生成的最终值就是CRC值。

    生成一个CRC的流程为:

    1

    预置一个16位寄存器为0FFFFH(全1),称之为CRC寄存器。

    2

    把数据帧中的第一个字节的8位与CRC寄存器中的低字节进行异或运算,结果存回CRC寄存器。

    3

    将CRC寄存器向右移一位,最高位填以0,最低位移出并检测。

    4

    如果最低位为0:重复第三步(下一次移位);如果最低位为1:将CRC寄存器与一个预设的固定值(0A001H)进行异或运算。

    5

    重复第三步和第四步直到8次移位。这样处理完了一个完整的八位。

    6

    重复第2步到第5步来处理下一个八位,直到所有的字节处理结束。

    7

    最终CRC寄存器的值就是CRC的值。

    此外还有一种利用预设的表格计算CRC的方法,它的主要特点是计算速度快,但是表格需要较大的存储空间,该方法此处不再赘述,请参阅相关资料。

    1.6

    通讯应用格式祥解

    本节所举实例将尽可能的使用如图所示的格式,(数字为16进制)。

    Addr

    Fun

    Data start  reg hi

    Data start  reg lo

    Data #of regs hi

    Data #of regs lo

    CRC16 lo

    CRC16hi

    01H

    03H

    00H

    00H

    00H

    03H

    05H

    CBH

    Addr:从机地址

    Fun:功能码

    Data start reg hi:数据起始地址 寄存器高字节

    Data start reg lo:数据起始地址 寄存器低字节

    Data #of reg hi:数据读取个数 寄存器高字节

    Data #of reg lo:数据读取个数 寄存器低字节

    CRC16 Hi: 循环冗余校验 高字节

    CRC16 Lo: 循环冗余校验 低字节

    CRC添加到消息中时,低字节先加入,然后高字节。

    CRC简单函数如下:(直接复制粘贴可用)

    static unsigned char auchCRCHi[]

    =

    {0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,

    0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,

    0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,

    0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,

    0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,

    0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,

    0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,

    0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,

    0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,

    0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,

    0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,

    0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,

    0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,

    0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,

    0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,

    0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,

    0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,

    0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,

    0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,

    0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,

    0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,

    0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,

    0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,

    0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,

    0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,

    0x80,0x41,0x00,0xC1,0x81,0x40

    } ;

    static char auchCRCLo[] = {

    0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,

    0x07,0xC7,0x05,0xC5,0xC4,0x04,0xCC,0x0C,0x0D,0xCD,

    0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,

    0x08,0xC8,0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,

    0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,0x14,0xD4,

    0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,

    0x11,0xD1,0xD0,0x10,0xF0,0x30,0x31,0xF1,0x33,0xF3,

    0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,

    0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,

    0x3B,0xFB,0x39,0xF9,0xF8,0x38,0x28,0xE8,0xE9,0x29,

    0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,

    0xEC,0x2C,0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,

    0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,0xA0,0x60,

    0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,

    0xA5,0x65,0x64,0xA4,0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,

    0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,

    0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,

    0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,0xB4,0x74,0x75,0xB5,

    0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,

    0x70,0xB0,0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,

    0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,0x9C,0x5C,

    0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,

    0x99,0x59,0x58,0x98,0x88,0x48,0x49,0x89,0x4B,0x8B,

    0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,

    0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,

    0x43,0x83,0x41,0x81,0x80,0x40

    };

    unsigned short CRC166(unsigned char *puchMsg,unsigned

    short usDataLen)

    {

    unsigned char uchCRCHi = 0xFF ;

    unsigned char uchCRCLo = 0xFF ;

    unsigned uIndex ;

    while (usDataLen--)

    {

    uIndex = uchCRCHi ^ *puchMsg++ ;

    uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;

    uchCRCLo = auchCRCLo[uIndex] ;

    }

    return ((uchCRCHi << 8) |

    uchCRCLo);

    }

    完毕!

    测试代码

    unsigned char TxData[8];

    TxData[0]=0x01;

    TxData[1]=0x06;

    TxData[2]=0x00;

    TxData[3]=0x00;

    TxData[4]=0x03;

    TxData[5]=0xE8;

    //调用计算CRC函数​

    unsigned short kk = CRC166(TxData,6);

    //以16进制窗口输出

    CString crc;

    crc.ReleaseBuffer();

    crc.Format(_T("%x"),kk);

    AfxMessageBox(crc);

    a4c26d1e5885305701be709a3d33442f.pngCRC输出

    ​以上主要参考:http://blog.csdn.net/qcwx828/article/details/7632140

    //校验码计算(正序计算方法)

    void CKonWin::CRC16_JiSuan(unsigned char data[],int

    length)

    {

    unsigned int CRC_code = 0x0000;

    unsigned int CRC16 = 0x8005;

    int i = 0,j = 0;

    for( i=0; i

    {

    CRC_code = CRC_code ^ ( ((unsigned int)data[i])

    << 8 );

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

    {

    if( CRC_code & 0x8000 )

    {

    CRC_code <<= 1;

    CRC_code = CRC_code ^ CRC16;

    }

    else

    CRC_code <<= 1; //等价于CRC_code =

    CRC_code<<1

    }

    }

    CRC_code = CRC_code & 0xFFFF;

    CString crc;

    crc.ReleaseBuffer();

    crc.Format(_T("%x"),CRC_code);

    AfxMessageBox(crc);

    }

    展开全文
  • 用C#实现CRC校验的算法,附有源代码
  • CRC校验C语言代码实现

    2021-09-15 16:06:20
    CRC校验码原理、实例、手动计算 - 步孤天 - 博客园(解释移位原理) https://blog.csdn.net/mish84/article/details/27528125(解释代码) //CRC16实现代码 uint16_t CrcSum(uint8_t *ptr, uint16_t len) { ...

    参考资料推荐

    [原创]CRC技术的实现与破解(10.21更新)-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com  (通俗解释)

    CRC校验码原理、实例、手动计算 - 步孤天 - 博客园(解释移位原理)

    https://blog.csdn.net/mish84/article/details/27528125(解释代码)

     //CRC16实现代码
    uint16_t CrcSum(uint8_t *ptr, uint16_t len) 
    {
        uint8_t i;
        uint16_t crc=0;
        
        while(len-- != 0) 
        {
            for(i=0x80; i!=0; i/=2) 
            {
                if((crc & 0x8000)!=0) 
                {
                    crc*=2;                                                                 //左移1位
                    crc^=0x1021;
                } /* 余式CRC乘以2再求CRC */
                else 
                {
                    crc*=2;
                }
                if((*ptr&i)!=0)
                {
                    crc^=0x1021; 
                }/* 再加上本位的CRC */
            }
            ptr++;
        }
        return (crc);
    }

    展开全文
  • CRC校验码的理解+CRC校验码算法代码

    万次阅读 2015-11-26 20:54:48
    CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一...CRC校验码的计算过程: 1,先约定一个校验码。
  • CRC校验原理及代码实现目录背景原理模2除法多项式计算流程代码实现()c语言实现c语言测试结果labview实现labview测试结果 目录 背景 在进行数据传输时,为了避免数据传输发生错误,需要对数据进行校验,从而产生了...
  • crc16校验 QT 实现

    2019-11-13 16:34:30
    2)crc_Checking(...):将有crc校验码的报文传入该函数,会检测你的报文中crc校验码是否正确。3)crcCalculation(...):将字符串传入该函数,自动计算出crc校验码并且添加到报文之后,返回携带crc校验码的新报文
  • crc32源代码32位crc校验码生成程序源代码vc++测试通过 http://hi.baidu.com/yanzi52351
  • CRC校验MATLAB代码

    热门讨论 2011-02-12 15:16:31
    可以方便完成8位、16位、24位CRC校验,经校验
  • CRC校验码的MATLAB和FPGA实现源程序CRC校验码的MATLAB和FPGA实现+源程序摘要:本设计首先介绍了CRC校验码工作的基本原理和生成原理,并利用Matlab软件对其进行了程序编程和编译仿真。重点分析了CRC校验码的FPGA具体...
  • CRC循环冗余校验码代码实现

    千次阅读 2018-08-13 12:36:44
    三、CRC循环冗余校验代码实现 四、程序执行结果 一、CRC循环冗余校验简介 现实的通信链路都不是理想的。也就是说,比特在传输过程中可能会产生差错:1可能变成0,0也可能变成1。这叫做比特差错。为了保证数据传输...
  • 是计算机网络通信技术当中的循环冗余校验CRC的C++实现,程序完整可运行,是在codeblocks环境当中编写的代码,程序的代码备注完整易懂。
  • CRC16校验程序代码

    2013-12-31 11:39:01
    是根据个人需要开发的,很简单,主要是进行CRC校验比对,输入一组数据和多项式进行判断计算,根据我的需要,不判断第一个数据,看图例:“5a”,其余数据一一判断,大家可以参考一下代码,根据自己需要适当修改
  • crc循环校验java代码实现privatebyte[]FormCrc(byte[]CRC_buf){//生成CRC-16校验码,返回的是整型形式的数据//System.out.println("**********生成CRC-16校验码");byte[]CRC=newbyte[2];intlen=CRC_buf.length;...
  • CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,713
精华内容 5,085
关键字:

crc校验码代码实现