• CRC校验(模型、手算、程序编写)


    一.模型

    1.WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位

    2.REFIN:true或false,如为true输入的原始数据的每个字节需要做个逆序的处理,注意:针对的每个字节,而不是整个数据,

    举例如下:

    以一个4字节的原始数据为例:

    3.INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。 它的值为全0或者全F,当全为0时,在算法开始前对数据(这个数据是根据RefIn的值得到的)后面补上CRC位数个0后就可以进行后续计算了。当全为1时,表示在算法开始前对数据的前CRC位数(高位)先和对应位数个1进行异或(即:前CRC位数的值按位取反),再在后面补上CRC位数个0,才进行后续计算。

    下面做的详细解释与计算过程

    4.POLY:多项式,以16进制表示。例如:CRC-16

    所以根据计算结果为0x18005,但是十六进制多项式,省略最高位1,最终结果0x8005与表格一致

    5.REFOUT:当其为false输出不做处理,当Refout为True,需要对输出数据做一次整个数据的逆序处理,注意:这里做的逆序和RefIn不同,它不是按字节逆序,而是整个逆序

    以CRC-32为例来说明,最后的数据为32位,当Refout为True时,翻转如下:

    6.XOROUT:结果与此参数异或后得到最终的CRC值。

    根据以上六个步骤我们可以进行计算,下面我们就用手算计算一边整体过程

    二、手算过程

    举例:0x06数据进行CRC-16/MODBUS校验

    (1)CRC-16/MODBUS的REFIN为true,需要进行逆序处理

    (2)CRC-16/MODBUS的INT位0xFFFF,将“1步骤”结果与0xFFFF异或处理

    (3)对“2步骤结果”进行左移16位补0,如果是CRC-8就左移8位补0,以此类推

     计算如下:

    知道了结果下面开始进行模2除法求余数

    (4)将上面结果与多项式进行计算

    第一种计算方式:带高位计算即与0x18005异或处理

    注:这里只异或计算右移8位而已,而方框的后面8位不计算了;是因为我们的原始数据只有0x06一个字节(我之前在这里栽跟头了,且注意,异或移动的字节是由于你原始数据有几个字节决定的)

    第二种计算方式:不含高位计算即与0x8005异或处理

    注:第二种计算均会判断起始位是否为1,是1右移一位再进行计算,箭头所标写 

     (5)因为CRC-16/MODBUS的Refout为True,对上面数据进行整体逆序

              上述结果:1111 1100 0100 0010 

              整体逆序:0100 0010 0011 1111

    (6)因为XOUT位0x0000,所以异或完还是不变,最终结果:0100 0010 0011 1111

    验证如下,计算无误

    下面下面再举例进行两个字节计算:0x06 0x06 进行CRC-16/MODBUS校验

    这里我手算就指计算第一种,第二种就不在写了,上面已经有写了一边

     

    看画红线处,这次校验数据是两个字节,所以我们计算的异或右移至两个字节宽度,这就与上面一个字节形成了对比,这下子大家应该都明白了

              上述结果:0100 0001 0100 1000

              整体逆序:0001 0010 1000 0010

    注:如遇到下面最终结果位数不足,需往前补0 ,以CRC-4举例,结果位数只有两位你就往前补两个0,使之结果为4位

    在线计算器:CRC(循环冗余校验)在线计算_ip33.com

    三、程序演变编写

    经过前两个个步骤的执行与体验,应该都有些许感悟,我们以手算母的了解其计算流程原理,那程序也是可以以此演变而来

    我们以CRC-8来计算

    /******************************************************************************
     * Name:    CRC-8               x8+x2+x+1
     * Poly:      0x07
     * Init:        0x00
     * Refin:    False
     * Refout:  False

     * Xorout:  0x00
     *****************************************************************************/
    uint8_t crc8(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0;    
        while(length--)
        {
            crc ^= *data++;      
            for ( i = 0; i < 8; i++ )
            {
                if ( crc & 0x80 )//1号
                    crc = (crc << 1) ^ 0x07;//2号
                else
                    crc <<= 1;
            }
        }
        return crc;
    }

    首先1号,这个判断是不是跟我们手算第二种方式一样,是都是先要判断起始位手否为1

    2号,是为1 需确定左移在异或多项式,是不是跟手算流程一至

    程序流程与手算流程其实是一致的,大家可以详细对比理解下

    下面在举一个例子,这个例子就有些差异,大家往下看

    /*****************************************************************************
     * Name:    CRC-8/ROHC          x8+x2+x+1
     * Poly:    0x07
     * Init:    0xFF
     * Refin:   True
     * Refout:  True

     * Xorout:  0x00
     * Note:
     *****************************************************************************/
    uint8_t crc8_rohc(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0xFF;        
        while(length--)
        {
            crc ^= *data++;          
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xE0;     
                else
                    crc = (crc >> 1);
            }
        }
        return crc;
    }
    很明显上面的数值是右移而不是像我们之前手算一样是左移,且异或的多项式也与模型上的数值0x07不一样,这次异或的是0xE0

    那我们再分析下,如下图手算验证,结果都是一致。原因使我们将多项式进行字节逆序处理,其实可以只管看到所有异或的数据都是相对应没有差别,在于右移与左移的不同

    所以这对  Refin:   True, Refout:  True,我们程序就进行了上述变换转化,多项式进行逆序

    上面是以CRC-8举例,如果是CRC-16呢,那么就是讲0x8005进行整体逆序就变成0xA001 

    完成!

    后续多个CRC模型程序,大家参考明显使用,只要手算你已经知道,那么程序都是由手算演变而来,道理一样的

    /******************************************************************************
     * Name:    CRC-4/ITU           x4+x+1
     * Poly:    0x03
     * Init:    0x00
     * Refin:   True
     * Refout:  True
     * Xorout:  0x00
     * Note:
     *****************************************************************************/
    uint8_t crc4_itu(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0;  
        while(length--)
        {
            crc ^= *data++;           
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0x0C;
                else
                    crc = (crc >> 1);
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-5/EPC           x5+x3+1
     * Poly:    0x09
     * Init:    0x09
     * Refin:   False
     * Refout:  False
     * Xorout:  0x00
     * Note:
     *****************************************************************************/
    uint8_t crc5_epc(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0x48;       
        while(length--)
        {
            crc ^= *data++;      
            for ( i = 0; i < 8; i++ )
            {
                if ( crc & 0x80 )
                    crc = (crc << 1) ^ 0x48;      
                else
                    crc <<= 1;
            }
        }
        return crc >> 3;
    }

    /******************************************************************************
     * Name:    CRC-5/ITU           x5+x4+x2+1
     * Poly:    0x15
     * Init:    0x00
     * Refin:   True
     * Refout:  True
     * Xorout:  0x00
     * Note:
     *****************************************************************************/
    uint8_t crc5_itu(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0;             
        while(length--)
        {
            crc ^= *data++;              
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0x15;
                else
                    crc = (crc >> 1);
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-5/USB           x5+x2+1
     * Poly:    0x05
     * Init:    0x1F
     * Refin:   True
     * Refout:  True
     * Xorout:  0x1F
     * Note:
     *****************************************************************************/
    uint8_t crc5_usb(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0x1F;                
        while(length--)
        {
            crc ^= *data++;        
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0x14;
                else
                    crc = (crc >> 1);
            }
        }
        return crc ^ 0x1F;
    }

    /******************************************************************************
     * Name:    CRC-6/ITU           x6+x+1
     * Poly:    0x03
     * Init:    0x00
     * Refin:   True
     * Refout:  True
     * Xorout:  0x00
     *****************************************************************************/
    uint8_t crc6_itu(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0;         
        while(length--)
        {
            crc ^= *data++; 
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0x30;
                else
                    crc = (crc >> 1);
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-7/MMC           x7+x3+1
     * Poly:    0x09
     * Init:    0x00
     * Refin:   False
     * Refout:  False
     * Xorout:  0x00
     * Use:     MultiMediaCard,SD,ect.
     *****************************************************************************/
    uint8_t crc7_mmc(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0;     
        while(length--)
        {
            crc ^= *data++;        
            for ( i = 0; i < 8; i++ )
            {
                if ( crc & 0x80 )
                    crc = (crc << 1) ^ 0x12;      
                else
                    crc <<= 1;
            }
        }
        return crc >> 1;
    }

    /******************************************************************************
     * Name:    CRC-8               x8+x2+x+1
     * Poly:    0x07
     * Init:    0x00
     * Refin:   False
     * Refout:  False
     * Xorout:  0x00
     * Note:
     *****************************************************************************/
    uint8_t crc8(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0;     
        while(length--)
        {
            crc ^= *data++;     
            for ( i = 0; i < 8; i++ )
            {
                if ( crc & 0x80 )
                    crc = (crc << 1) ^ 0x07;
                else
                    crc <<= 1;
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-8/ITU           x8+x2+x+1
     * Poly:    0x07
     * Init:    0x00
     * Refin:   False
     * Refout:  False
     * Xorout:  0x55
     * Alias:   CRC-8/ATM
     *****************************************************************************/
    uint8_t crc8_itu(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0;     
        while(length--)
        {
            crc ^= *data++;    
            for ( i = 0; i < 8; i++ )
            {
                if ( crc & 0x80 )
                    crc = (crc << 1) ^ 0x07;
                else
                    crc <<= 1;
            }
        }
        return crc ^ 0x55;
    }

    /******************************************************************************
     * Name:    CRC-8/ROHC          x8+x2+x+1
     * Poly:    0x07
     * Init:    0xFF
     * Refin:   True
     * Refout:  True
     * Xorout:  0x00
     * Note:
     *****************************************************************************/
    uint8_t crc8_rohc(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0xFF;    
        while(length--)
        {
            crc ^= *data++;         
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xE0;     
                else
                    crc = (crc >> 1);
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-8/MAXIM         x8+x5+x4+1
     * Poly:    0x31
     * Init:    0x00
     * Refin:   True
     * Refout:  True
     * Xorout:  0x00
     * Alias:   DOW-CRC,CRC-8/IBUTTON
     * Use:     Maxim(Dallas)'s some devices,e.g. DS18B20
     *****************************************************************************/
    uint8_t crc8_maxim(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint8_t crc = 0;       
        while(length--)
        {
            crc ^= *data++;    
            for (i = 0; i < 8; i++)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0x8C;       
                else
                    crc >>= 1;
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-16/IBM          x16+x15+x2+1
     * Poly:    0x8005
     * Init:    0x0000
     * Refin:   True
     * Refout:  True
     * Xorout:  0x0000
     * Alias:   CRC-16,CRC-16/ARC,CRC-16/LHA
     *****************************************************************************/
    uint16_t crc16_ibm(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0;     
        while(length--)
        {
            crc ^= *data++;       
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xA001;     
                else
                    crc = (crc >> 1);
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-16/MAXIM        x16+x15+x2+1
     * Poly:    0x8005
     * Init:    0x0000
     * Refin:   True
     * Refout:  True
     * Xorout:  0xFFFF
     * Note:
     *****************************************************************************/
    uint16_t crc16_maxim(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0;     
        while(length--)
        {
            crc ^= *data++;      
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xA001;      
                else
                    crc = (crc >> 1);
            }
        }
        return ~crc;    // crc^0xffff
    }

    /******************************************************************************
     * Name:    CRC-16/USB          x16+x15+x2+1
     * Poly:    0x8005
     * Init:    0xFFFF
     * Refin:   True
     * Refout:  True
     * Xorout:  0xFFFF
     * Note:
     *****************************************************************************/
    uint16_t crc16_usb(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0xffff;      
        while(length--)
        {
            crc ^= *data++;       
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xA001;        
                else
                    crc = (crc >> 1);
            }
        }
        return ~crc;    // crc^0xffff
    }

    /******************************************************************************
     * Name:    CRC-16/MODBUS       x16+x15+x2+1
     * Poly:    0x8005
     * Init:    0xFFFF
     * Refin:   True
     * Refout:  True
     * Xorout:  0x0000
     * Note:
     *****************************************************************************/
    uint16_t crc16_modbus(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0xffff;        // Initial value
        while(length--)
        {
            crc ^= *data++;        
                printf("%04x\n", crc);
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xA001;     
                else
                    crc = (crc >> 1);
                printf("%04x\n", crc);
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-16/CCITT        x16+x12+x5+1
     * Poly:    0x1021
     * Init:    0x0000
     * Refin:   True
     * Refout:  True
     * Xorout:  0x0000
     * Alias:   CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT
     *****************************************************************************/
    uint16_t crc16_ccitt(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0;        // Initial value
        while(length--)
        {
            crc ^= *data++;    
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0x8408;       
                else
                    crc = (crc >> 1);
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-16/CCITT-FALSE   x16+x12+x5+1
     * Poly:    0x1021
     * Init:    0xFFFF
     * Refin:   False
     * Refout:  False
     * Xorout:  0x0000
     * Note:
     *****************************************************************************/
    uint16_t crc16_ccitt_false(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0xffff;        //Initial value
        while(length--)
        {
            crc ^= (uint16_t)(*data++) << 8; 
            for (i = 0; i < 8; ++i)
            {
                if ( crc & 0x8000 )
                    crc = (crc << 1) ^ 0x1021;
                else
                    crc <<= 1;
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-16/X25          x16+x12+x5+1
     * Poly:    0x1021
     * Init:    0xFFFF
     * Refin:   True
     * Refout:  True
     * Xorout:  0XFFFF
     * Note:
     *****************************************************************************/
    uint16_t crc16_x25(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0xffff;       
        while(length--)
        {
            crc ^= *data++;        
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0x8408;      
                else
                    crc = (crc >> 1);
            }
        }
        return ~crc;             
    }

    /******************************************************************************
     * Name:    CRC-16/XMODEM       x16+x12+x5+1
     * Poly:    0x1021
     * Init:    0x0000
     * Refin:   False
     * Refout:  False
     * Xorout:  0x0000
     * Alias:   CRC-16/ZMODEM,CRC-16/ACORN
     *****************************************************************************/
    uint16_t crc16_xmodem(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0;            // Initial value
        while(length--)
        {
            crc ^= (uint16_t)(*data++) << 8; 
            for (i = 0; i < 8; ++i)
            {
                if ( crc & 0x8000 )
                    crc = (crc << 1) ^ 0x1021;
                else
                    crc <<= 1;
            }
        }
        return crc;
    }

    /******************************************************************************
     * Name:    CRC-16/DNP          x16+x13+x12+x11+x10+x8+x6+x5+x2+1
     * Poly:    0x3D65
     * Init:    0x0000
     * Refin:   True
     * Refout:  True
     * Xorout:  0xFFFF
     * Use:     M-Bus,ect.
     *****************************************************************************/
    uint16_t crc16_dnp(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint16_t crc = 0;      
        while(length--)
        {
            crc ^= *data++;        
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xA6BC;    
                else
                    crc = (crc >> 1);
            }
        }
        return ~crc;            
    }

    /******************************************************************************
     * Name:    CRC-32  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
     * Poly:    0x4C11DB7
     * Init:    0xFFFFFFF
     * Refin:   True
     * Refout:  True
     * Xorout:  0xFFFFFFF
     * Alias:   CRC_32/ADCCP
     * Use:     WinRAR,ect.
     *****************************************************************************/
    uint32_t crc32(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint32_t crc = 0xffffffff;      
        while(length--)
        {
            crc ^= *data++;           
            for (i = 0; i < 8; ++i)
            {
                if (crc & 1)
                    crc = (crc >> 1) ^ 0xEDB88320;
                else
                    crc = (crc >> 1);
            }
        }
        return ~crc;
    }

    /******************************************************************************
     * Name:    CRC-32/MPEG-2  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
     * Poly:    0x4C11DB7
     * Init:    0xFFFFFFF
     * Refin:   False
     * Refout:  False
     * Xorout:  0x0000000
     *****************************************************************************/
    uint32_t crc32_mpeg_2(uint8_t *data, uint16_t length)
    {
        uint8_t i;
        uint32_t crc = 0xffffffff;  // Initial value
        while(length--)
        {
            crc ^= (uint32_t)(*data++) << 24;
            for (i = 0; i < 8; ++i)
            {
                if ( crc & 0x80000000 )
                    crc = (crc << 1) ^ 0x04C11DB7;
                else
                    crc <<= 1;
            }
        }
        return crc;
    }
     

  • 相关阅读:
    网络安全-抓包和IP包头分析
    地理标志农产品质量安全风险评估及预警研究
    AD - 将修改后的 PCB 封装更新到当前 PCB 中
    安卓窗体显示状态
    【yolo系列:yolov7改进wise-iou】
    C++的类型转换
    vue根据文字长短展示跑马灯效果
    Python地理数据处理 十八:arcpy批量处理数据之栅格图像的统计分析
    计算机毕设源码网站springboot毕业设计管理系统
    java计算机毕业设计基于ssm的医药进出口交易系统(源代码+数据库+Lw文档)
  • 原文地址:https://blog.csdn.net/qq_38295600/article/details/126399048