数据校验--CRC校验

2024-05-01 13:48
文章标签 数据 校验 crc

本文主要是介绍数据校验--CRC校验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

工作原理:
    CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。
    循环冗余检查(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)*2^R),这样C(x)的右边就会空出R位,这就是校验码的位置。
    用 C(x)*2^R 除以生成多项式G(x)得到的余数就是校验码。
    任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。
基本概念:
    对应关系:
        多项式和二进制数有直接对应关系:X的最高幂次对应二进制数的最高位,以下各位对应多项式的各幂次,有此幂次项对应1,无此幂次项对应0。
        可以看出:X的最高幂次为R,转换成对应的二进制数有R+1位。
        多项式包括生成多项式G(X)和信息多项式C(X)。
        如生成多项式为G(X)=X4+X3+X+1, 可转换为二进制数码11011
        而发送信息位 101111,可转换为数据多项式为C(X)=X5+X3+X2+X+1。
    生成多项式:
        是接受方和发送方的一个约定,也就是一个二进制数,在整个传输过程中,这个数始终保持不变。
        在发送方,利用生成多项式对信息多项式做模2除生成校验码。在接收方利用生成多项式对收到的编码多项式做模2除检测和确定错误位置。
        应满足以下条件:
            A、生成多项式的最高位和最低位必须为1。
            B、当被传送信息(CRC码)任何一位发生错误时,被生成多项式做除后应该使余数不为0。
            C、不同位发生错误时,应该使余数不同。
            D、对余数继续做除,应使余数循环。
    校验码位数:
        CRC校验码位数 = 生成多项式位数 - 1。注意有些生成多项式的简记式中将生成多项式的最高位1省略了。
    生成步骤:
        1、将X的最高次幂为R的生成多项式G(X)转换成对应的R+1位二进制数。
        2、将信息码左移R位,相当于对应的信息多项式C(X)*2^R。
        3、用生成多项式(二进制数)对信息码做除,得到R位的余数(注意:这里的二进制做除法得到的余数其实是模2除法得到的余数,并不等于其对应十进制数做除法得到的余数。)。
        4、将余数拼到信息码左移后空出的位置,得到完整的CRC码。
        例:假设使用的生成多项式是G(X)=X3+X+1。4位的原始报文为1010,求编码后的报文。
        1、将生成多项式G(X)=X3+X+1转换成对应的二进制除数1011。
        2、此题生成多项式有4位(R+1)(注意:4位的生成多项式计算所得的校验码为3位,R为校验码位数),要把原始报文C(X)左移3(R)位变成1010 000
        3、用生成多项式对应的二进制数对左移3位后的原始报文进行模2除(高位对齐),相当于按位异或:
        1010000
        1011
        ————————————
        0001000
        1000
        1011
        ————————————
        0011
        得到的余位011,所以最终编码为:1010 011
生成方法:
    借助于模2除法则,其余数为校验字段。
    例如:信息字段代码为: 1011001;对应m(x)=x6+x4+x3+1
    假设生成多项式为:g(x)=x4+x3+1;则对应g(x)的代码为: 11001
    x^4*m(x)=x10+x8+x7+x4 对应的代码记为:10110010000(相当于1011001<<4);
    采用模2除法则: 得余数为: 1010(即校验字段为:1010)
    发送方:发出的传输字段为: 10110011010 信息字段+校验字段
    接收方:使用相同的生成码进行校验:接收到的字段/生成码(二进制除法)如果能够除尽,则正确,
    给出余数(1010)的计算步骤:
    除法没有数学上的含义,而是采用计算机的模二除法,即除数和被除数做异或运算。进行异或运算时除数和被除数最高位对齐,按位异或。
    10110010000
    11001
    ————————————
    01111010000
    1111010000
    11001
    ————————————
    0011110000
    11110000
    11001
    ————————————
    00111000
    111000
    11001
    ————————————
    001010
    1010
    则四位CRC校验码就为:1010。
    利用CRC进行检错的过程可简单描述为:在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的r位监督码(CRC码),附在原始信息后边,构成一个新的二进制码序列数共k+r位,
    后发送出去。在接收端,根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。这个规则,在差错控制理论中称为“生成多项式”。
位宽:
    有一点要特别注意:生成多项式经常会说到多项式的位宽(Width,简记为W),这个位宽不是多项式对应的二进制数的位数,而是二进制位数减1。比如CRC8中用到的位宽为8的生成多项式,
    其实对应得二进制数有九位:100110001。另外一点,多项式表示和二进制表示都很繁琐,交流起来不方便,因此,多用16进制简写法来表示,因为生成多项式的最高位肯定为1,
    最高位的位置由位宽可知,故在简记式中,将最高的1统一去掉了,如CRC32的生成多项式简记为04C11DB7实际上表示的是104C11DB7。


CRC算法的编程实现:
    STM32硬件实现:
        1. 开启CRC单元的时钟。RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE)
        2. 复位CRC模块(设置CRC_CR=0x01),这个操作把CRC余数初始化为0xFFFFFFFF  CRC_ResetDR(void) 
        3. 把要计算的数据按逐个地写入CRC_DR寄存器  
            uint32_t CRC_CalcCRC(uint32_t Data); 将一个数据写入CRC_DR寄存器,返回值为计算结果。
            uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength);计算一个数组的CRC 值。
        4. 写完所有的数据字后,从CRC_DR寄存器读出计算的结果
        例程:
        #include "stm32f10x.h"
        #define BUFFER_SIZE    114
        static const uint32_t DataBuffer[BUFFER_SIZE] =
          {
            0x00001021, 0x20423063, 0x408450a5, 0x60c670e7, 0x9129a14a, 0xb16bc18c,
            0xd1ade1ce, 0xf1ef1231, 0x32732252, 0x52b54294, 0x72f762d6, 0x93398318,
            0xa35ad3bd, 0xc39cf3ff, 0xe3de2462, 0x34430420, 0x64e674c7, 0x44a45485,
            0xa56ab54b, 0x85289509, 0xf5cfc5ac, 0xd58d3653, 0x26721611, 0x063076d7,
            0x569546b4, 0xb75ba77a, 0x97198738, 0xf7dfe7fe, 0xc7bc48c4, 0x58e56886,
            0x78a70840, 0x18612802, 0xc9ccd9ed, 0xe98ef9af, 0x89489969, 0xa90ab92b,
            0x4ad47ab7, 0x6a961a71, 0x0a503a33, 0x2a12dbfd, 0xfbbfeb9e, 0x9b798b58,
            0xbb3bab1a, 0x6ca67c87, 0x5cc52c22, 0x3c030c60, 0x1c41edae, 0xfd8fcdec,
            0xad2abd0b, 0x8d689d49, 0x7e976eb6, 0x5ed54ef4, 0x2e321e51, 0x0e70ff9f,
            0xefbedfdd, 0xcffcbf1b, 0x9f598f78, 0x918881a9, 0xb1caa1eb, 0xd10cc12d,
            0xe16f1080, 0x00a130c2, 0x20e35004, 0x40257046, 0x83b99398, 0xa3fbb3da,
            0xc33dd31c, 0xe37ff35e, 0x129022f3, 0x32d24235, 0x52146277, 0x7256b5ea,
            0x95a88589, 0xf56ee54f, 0xd52cc50d, 0x34e224c3, 0x04817466, 0x64475424,
            0x4405a7db, 0xb7fa8799, 0xe75ff77e, 0xc71dd73c, 0x26d336f2, 0x069116b0,
            0x76764615, 0x5634d94c, 0xc96df90e, 0xe92f99c8, 0xb98aa9ab, 0x58444865,
            0x78066827, 0x18c008e1, 0x28a3cb7d, 0xdb5ceb3f, 0xfb1e8bf9, 0x9bd8abbb,
            0x4a755a54, 0x6a377a16, 0x0af11ad0, 0x2ab33a92, 0xed0fdd6c, 0xcd4dbdaa,
            0xad8b9de8, 0x8dc97c26, 0x5c644c45, 0x3ca22c83, 0x1ce00cc1, 0xef1fff3e,
            0xdf7caf9b, 0xbfba8fd9, 0x9ff86e17, 0x7e364e55, 0x2e933eb2, 0x0ed11ef0
          };
        __IO uint32_t CRCValue = 0;
        /**
          * @brief  Main program.
          * @param  None
          * @retval None
          */
        int main(void)
        {
          /*!< At this stage the microcontroller clock setting is already configured, 
               this is done through SystemInit() function which is called from startup
               file (startup_stm32f10x_xx.s) before to branch to application main.
               To reconfigure the default setting of SystemInit() function, refer to
               system_stm32f10x.c file
             */       
          /* Enable CRC clock */
          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
          /* Compute the CRC of "DataBuffer" */
          CRCValue = CRC_CalcBlockCRC((uint32_t *)DataBuffer, BUFFER_SIZE);
          while (1)
          {
          }
        }


    软件编程(CRC32):
    #define poly 0xEDB88320
    int crc32(char *addr, int num, int crc)
    {
        int i;

        for (; num>0; num--)              /* Step through bytes in memory */
        {
          crc = crc ^ *addr++;            /* Fetch byte from memory, XOR into CRC */
          for (i=0; i<8; i++)             /* Prepare to rotate 8 bits */
          {
            if (crc & 1)                  /* b0 is set... */
              crc = (crc >> 1) ^ poly;    /* rotate and XOR with ZIP polynomic */
            else                          /* b0 is clear... */
              crc >>= 1;                  /* just rotate */
            }                             /* Loop for 8 bits */
        }                                 /* Loop until num=0 */
          return(crc);                    /* Return updated CRC */
    }

这篇关于数据校验--CRC校验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/951857

相关文章

Redis的数据过期策略和数据淘汰策略

《Redis的数据过期策略和数据淘汰策略》本文主要介绍了Redis的数据过期策略和数据淘汰策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录一、数据过期策略1、惰性删除2、定期删除二、数据淘汰策略1、数据淘汰策略概念2、8种数据淘汰策略

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

Python给Excel写入数据的四种方法小结

《Python给Excel写入数据的四种方法小结》本文主要介绍了Python给Excel写入数据的四种方法小结,包含openpyxl库、xlsxwriter库、pandas库和win32com库,具有... 目录1. 使用 openpyxl 库2. 使用 xlsxwriter 库3. 使用 pandas 库

SpringBoot定制JSON响应数据的实现

《SpringBoot定制JSON响应数据的实现》本文主要介绍了SpringBoot定制JSON响应数据的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录前言一、如何使用@jsonView这个注解?二、应用场景三、实战案例注解方式编程方式总结 前言

使用Python在Excel中创建和取消数据分组

《使用Python在Excel中创建和取消数据分组》Excel中的分组是一种通过添加层级结构将相邻行或列组织在一起的功能,当分组完成后,用户可以通过折叠或展开数据组来简化数据视图,这篇博客将介绍如何使... 目录引言使用工具python在Excel中创建行和列分组Python在Excel中创建嵌套分组Pyt

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

在Mysql环境下对数据进行增删改查的操作方法

《在Mysql环境下对数据进行增删改查的操作方法》本文介绍了在MySQL环境下对数据进行增删改查的基本操作,包括插入数据、修改数据、删除数据、数据查询(基本查询、连接查询、聚合函数查询、子查询)等,并... 目录一、插入数据:二、修改数据:三、删除数据:1、delete from 表名;2、truncate

Java实现Elasticsearch查询当前索引全部数据的完整代码

《Java实现Elasticsearch查询当前索引全部数据的完整代码》:本文主要介绍如何在Java中实现查询Elasticsearch索引中指定条件下的全部数据,通过设置滚动查询参数(scrol... 目录需求背景通常情况Java 实现查询 Elasticsearch 全部数据写在最后需求背景通常情况下

Java中注解与元数据示例详解

《Java中注解与元数据示例详解》Java注解和元数据是编程中重要的概念,用于描述程序元素的属性和用途,:本文主要介绍Java中注解与元数据的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参... 目录一、引言二、元数据的概念2.1 定义2.2 作用三、Java 注解的基础3.1 注解的定义3.2 内

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据