CRC校验(循环冗余校验)小知识

CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将得到的结果附在帧的后面,接收设备也执行类似的算法,以保证数据传输的正确性和完整性。

CRC算法参数模型解释:
NAME:参数模型名称。
WIDTH:宽度,即CRC比特数。
POLY:生成项的简写,以16进制表示。例如:CRC-32即是0x04C11DB7,忽略了最高位的"1",即完整的生成项是0x104C11DB7。
INIT:这是算法开始时寄存器(crc)的初始化预置值,十六进制表示。
REFIN:待测数据的每个字节是否按位反转,True或False。
REFOUT:在计算后之后,异或输出之前,整个数据是否按位反转,True或False。
XOROUT:计算结果与此参数异或后得到最终的CRC值。

常见CRC参数模型如下:

CRC算法名称

多项式公式

宽度

多项式

初始值

结果异或值

输入反转

输出反转

CRC-4/ITU

x4 + x + 1

4

03

00

00

true

true

CRC-5/EPC

x5 + x3 + 1

5

09

09

00

false

false

CRC-5/ITU

x5 + x4 + x2 + 1

5

15

00

00

true

true

CRC-5/USB

x5 + x2 + 1

5

05

1F

1F

true

true

CRC-6/ITU

x6 + x + 1

6

03

00

00

true

true

CRC-7/MMC

x7 + x3 + 1

7

09

00

00

false

false

CRC-8

x8 + x2 + x + 1

8

07

00

00

false

false

CRC-8/ITU

x8 + x2 + x + 1

8

07

00

55

false

false

CRC-8/ROHC

x8 + x2 + x + 1

8

07

FF

00

true

true

CRC-8/MAXIM

x8 + x5 + x4 + 1

8

31

00

00

true

true

CRC-16/IBM

x16 + x15 + x2 + 1

16

8005

0000

0000

true

true

CRC-16/MAXIM

x16 + x15 + x2 + 1

16

8005

0000

FFFF

true

true

CRC-16/USB

x16 + x15 + x2 + 1

16

8005

FFFF

FFFF

true

true

CRC-16/MODBUS

x16 + x15 + x2 + 1

16

8005

FFFF

0000

true

true

CRC-16/CCITT

x16 + x12 + x5 + 1

16

1021

0000

0000

true

true

CRC-16/CCITT-FALSE

x16 + x12 + x5 + 1

16

1021

FFFF

0000

false

false

CRC-16/X25

x16 + x12 + x5 + 1

16

1021

FFFF

FFFF

true

true

CRC-16/XMODEM

x16 + x12 + x5 + 1

16

1021

0000

0000

false

false

CRC-16/DNP

x16 + x13 + x12 + x11 + x10 + x8 + x6 + x5 + x2 + 1

16

3D65

0000

FFFF

true

true

CRC-32

x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1

32

04C11DB7

FFFFFFFF

FFFFFFFF

true

true

CRC-32/MPEG-2

x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1

32

04C11DB7

FFFFFFFF

00000000

false

false

uint8_t crc4_itu(uint8_t *data, uint_len length);

uint8_t crc5_epc(uint8_t *data, uint_len length);

uint8_t crc5_itu(uint8_t *data, uint_len length);

uint8_t crc5_usb(uint8_t *data, uint_len length);

uint8_t crc6_itu(uint8_t *data, uint_len length);

uint8_t crc7_mmc(uint8_t *data, uint_len length);

uint8_t crc8(uint8_t *data, uint_len length);

uint8_t crc8_itu(uint8_t *data, uint_len length);

uint8_t crc8_rohc(uint8_t *data, uint_len length);

uint8_t crc8_maxim(uint8_t *data, uint_len length);//DS18B20

uint16_t crc16_ibm(uint8_t *data, uint_len length);

uint16_t crc16_maxim(uint8_t *data, uint_len length);

uint16_t crc16_usb(uint8_t *data, uint_len length);

uint16_t crc16_modbus(uint8_t *data, uint_len length);

uint16_t crc16_ccitt(uint8_t *data, uint_len length);

uint16_t crc16_ccitt_false(uint8_t *data, uint_len length);

uint16_t crc16_x25(uint8_t *data, uint_len length);

uint16_t crc16_xmodem(uint8_t *data, uint_len length);

uint16_t crc16_dnp(uint8_t *data, uint_len length);

uint32_t crc32(uint8_t *data, uint_len length);

uint32_t crc32_mpeg_2(uint8_t *data, uint_len length);/******************************************************************************

 * 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, uint_len length){

    uint8_t i;

    uint8_t crc = 0;                // Initial value

    while(length--)

    {

        crc ^= *data++;                 // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0x0C;// 0x0C = (reverse 0x03)>>(8-4)

            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, uint_len length){

    uint8_t i;

    uint8_t crc = 0x48;        // Initial value: 0x48 = 0x09<<(8-5)

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; data++;

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

        {

            if ( crc & 0x80 )

                crc = (crc << 1) ^ 0x48;        // 0x48 = 0x09<<(8-5)

            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, uint_len length){

    uint8_t i;

    uint8_t crc = 0;                // Initial value

    while(length--)

    {

        crc ^= *data++;                 // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0x15;// 0x15 = (reverse 0x15)>>(8-5)

            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, uint_len length){

    uint8_t i;

    uint8_t crc = 0x1F;                // Initial value

    while(length--)

    {

        crc ^= *data++;                 // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0x14;// 0x14 = (reverse 0x05)>>(8-5)

            else

                crc = (crc >> 1);

        }

    }

    return crc ^ 0x1F;}

 /******************************************************************************

 * Name:    CRC-6/ITU           x6+x+1

 * Poly:    0x03

 * Init:    0x00

 * Refin:   True

 * Refout:  True

 * Xorout:  0x00

 * Note:

 *****************************************************************************/

uint8_t crc6_itu(uint8_t *data, uint_len length){

    uint8_t i;

    uint8_t crc = 0;         // Initial value

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0x30;// 0x30 = (reverse 0x03)>>(8-6)

            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, uint_len length){

    uint8_t i;

    uint8_t crc = 0;        // Initial value

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; data++;

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

        {

            if ( crc & 0x80 )

                crc = (crc << 1) ^ 0x12;        // 0x12 = 0x09<<(8-7)

            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, uint_len length){

    uint8_t i;

    uint8_t crc = 0;        // Initial value

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; 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, uint_len length){

    uint8_t i;

    uint8_t crc = 0;        // Initial value

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; 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, uint_len length){

    uint8_t i;

    uint8_t crc = 0xFF;         // Initial value

    while(length--)

    {

        crc ^= *data++;            // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0xE0;        // 0xE0 = reverse 0x07

            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, uint_len length){

    uint8_t i;

    uint8_t crc = 0;         // Initial value

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0x8C;        // 0x8C = reverse 0x31

            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, uint_len length){

    uint8_t i;

    uint16_t crc = 0;        // Initial value

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0xA001;        // 0xA001 = reverse 0x8005

            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, uint_len length){

    uint8_t i;

    uint16_t crc = 0;        // Initial value

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0xA001;        // 0xA001 = reverse 0x8005

            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, uint_len length){

    uint8_t i;

    uint16_t crc = 0xffff;        // Initial value

    while(length--)

    {

        crc ^= *data++;            // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0xA001;        // 0xA001 = reverse 0x8005

            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, uint_len length){

    uint8_t i;

    uint16_t crc = 0xffff;        // Initial value

    while(length--)

    {

        crc ^= *data++;            // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0xA001;        // 0xA001 = reverse 0x8005

            else

                crc = (crc >> 1);

        }

    }

    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, uint_len length){

    uint8_t i;

    uint16_t crc = 0;        // Initial value

    while(length--)

    {

        crc ^= *data++;        // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0x8408;        // 0x8408 = reverse 0x1021

            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, uint_len length){

    uint8_t i;

    uint16_t crc = 0xffff;        //Initial value

    while(length--)

    {

        crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint6_t)(*data)<<8; data++;

        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, uint_len length){

    uint8_t i;

    uint16_t crc = 0xffff;        // Initial value

    while(length--)

    {

        crc ^= *data++;            // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0x8408;        // 0x8408 = reverse 0x1021

            else

                crc = (crc >> 1);

        }

    }

    return ~crc;                // crc^Xorout}

 /******************************************************************************

 * 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, uint_len length){

    uint8_t i;

    uint16_t crc = 0;            // Initial value

    while(length--)

    {

        crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint16_t)(*data)<<8; data++;

        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, uint_len length){

    uint8_t i;

    uint16_t crc = 0;            // Initial value

    while(length--)

    {

        crc ^= *data++;            // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0xA6BC;        // 0xA6BC = reverse 0x3D65

            else

                crc = (crc >> 1);

        }

    }

    return ~crc;                // crc^Xorout}

 /******************************************************************************

 * 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, uint_len length){

    uint8_t i;

    uint32_t crc = 0xffffffff;        // Initial value

    while(length--)

    {

        crc ^= *data++;                // crc ^= *data; data++;

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

        {

            if (crc & 1)

                crc = (crc >> 1) ^ 0xEDB88320;// 0xEDB88320= reverse 0x04C11DB7

            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

 * Note:

 *****************************************************************************/

uint32_t crc32_mpeg_2(uint8_t *data, uint_len length){

    uint8_t i;

    uint32_t crc = 0xffffffff;  // Initial value

    while(length--)

    {

        crc ^= (uint32_t)(*data++) << 24;// crc ^=(uint32_t)(*data)<<24; data++;

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

        {

            if ( crc & 0x80000000 )

                crc = (crc << 1) ^ 0x04C11DB7;

            else

                crc <<= 1;

        }

    }

    return crc;}

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CRC(循环冗余校验)是一种重要的线性分组码,用于实现差错控制。它具有检错和纠错能力强的特点,在计算机信息通信领域被广泛使用。CRC算法校验的检错能力极强,且检测成本较低,因此在对于编码器和电路的检测中使用较为广泛。从检错的正确性与速度、成本等方面,都比奇偶校验等校验方式具有优势。因而,CRC成为计算机信息通信领域最为普遍的校验方式。CRC的原理是根据多项式得到CRC除数,通过对数据进行除法运算得到校验码。生成多项式是标准规定的,发送方和接收方必须事先商定一个生成多项式G(x),其高位和低位必须是1。CRC在数据存储、数据通信等领域都有广泛的应用,例如在读软盘上的文件、解压ZIP文件时,偶尔会碰到“Bad CRC”错误。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [CRC 循环冗余校验](https://blog.csdn.net/zhangduang_KHKW/article/details/121852304)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [循环冗余校验-CRC](https://blog.csdn.net/qq_43441284/article/details/124945020)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值