Cyclic Redundancy Check 循环冗余校验

一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术, 主要用来检测或校验数据传输或者保存后可能出现的错误。

它是利用除法及余数的原理来作错误侦测的。

CRC参数模型

一个完整的CRC参数模型应该包含以下信息:WIDTH,POLY,INIT,REFIN,REFOUT,XOROUT。

  • NAME:参数模型名称。
  • WIDTH:宽度,即生成的CRC数据位宽,如CRC-8,生成的CRC为8位
  • POLY:十六进制多项式,省略最高位1,如 x8 + x2 + x + 1,二进制为1 0000 0111,省略最高位1,转换为十六进制为0x07。
  • INIT:CRC初始值,和WIDTH位宽一致。
  • REFIN:true或false,在进行计算之前,原始数据(每个字节)是否翻转,如原始数据:0x34 = 0011 0100,如果REFIN为true,进行翻转之后为0010 1100 = 0x2c
  • REFOUT:true或false,运算完成之后,得到的CRC值(整个数据)是否进行翻转,如计算得到的CRC值:0x97 = 1001 0111,如果REFOUT为true,进行翻转之后为11101001 = 0xE9。
  • XOROUT:计算结果与此参数进行异或运算后得到最终的CRC值,和WIDTH位宽一致。

CRC计算

问:原始数据:0x34,使用CRC-8/MAXIN参数模型,求CRC值?

根据上表,CRC-8/MAXIN参数模型参数如下:

POLY = 0x31 = 0011 0001(最高位1已经省略)

INIT = 0x00

XOROUT = 0x00

REFIN = TRUE

REFOUT = TRUE

计算过程

  1. 原始数据 = 0x34 = 0011 0100,多项式 = 0x31 = 1 0011 0001
  2. INIT = 00,原始数据高8位和初始值进行异或运算保持不变。
  3. REFIN为TRUE,需要先对原始数据进行翻转:0011 0100 > 0010 1100
  4. 原始数据左移8位,即后面补8个0:0010 1100 0000 0000
  5. 把处理之后的数据和多项式进行模2除法,求得余数:

原始数据:0010 1100 0000 0000 = 10 1100 0000 0000

多项式:1 0011 0001

模2除法取余数低8位:1111 1011

  1. 与XOROUT进行异或,1111 1011 xor 0000 0000 = 1111 1011
  2. 因为REFOUT为TRUE,对结果进行翻转得到最终的CRC-8值:1101 1111 = 0xDF
  3. 数据+CRC:0011 0100 1101 1111 = 34DF,相当于原始数据左移8位+余数。

C source code
GitHub - whik/crc-lib-c: 基于C语言的CRC校验库,包括常用的21个CRC参数模型实现基于C语言的CRC校验库,包括常用的21个CRC参数模型实现. Contribute to whik/crc-lib-c development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/whik/crc-lib-c【注】如REFIN/REFOUT 为 TRUE,即需要对数据进行反转时,可以从数据的最低bit开始计算,则可避免反转操作。

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

 * 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;        // 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;

}

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

 *

 * Function:    crc32()

 *

 * Description: Compute the CRC of a given message.

 *

 * Notes:

 *

 * Returns:        The CRC of the message.

 *

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

uint32_t crc32(const void *data, int nBytes)

{

    crc            remainder = INITIAL_REMAINDER;

    int            byte;

    unsigned char  bit;

    unsigned char const *message = data;

    /*

     * Perform modulo-2 division, a byte at a time.

     */

    for (byte = 0; byte < nBytes; ++byte) {

        /*

         * Bring the next byte into the remainder.

         */

        remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8));

        /*

         * Perform modulo-2 division, a bit at a time.

         */

        for (bit = 8; bit > 0; --bit) {

            /*

             * Try to divide the current data bit.

             */

            if (remainder & TOPBIT) {

                remainder = (remainder << 1) ^ POLYNOMIAL;

            } else {

                remainder = (remainder << 1);

            }

        }

    }

    /*

     * The final remainder is the CRC result.

     */

    return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);

}   /* crc32() */

在线计算工具

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

参考资料

CRC校验原理及实现 - 知乎 (zhihu.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值