CRC实现

常见CRC算法定义如下

CRC算法

多项式公式

多项式

初始值

结果异或值

输入反转

输出反转

CRC8

x8+x2+x1+1

07

00

00

false

false

CRC8/ITU

07

00

55

false

false

CRC8/ROHC

07

FF

00

true

true

CRC8/MAXIM

x8+x5+x4+1

31

00

00

true

true

CRC16/IBM

x16 + x15 + x2 + 1

8005

0000

0000

true

true

CRC16/MAXIM

8005

0000

FFFF

true

true

CRC16/USB

8005

FFFF

FFFF

true

true

CRC16/MODBUS

8005

FFFF

0000

true

true

CRC16/CCITT

x16 + x12 + x5 + 1

1021

0000

0000

true

true

CRC16/CCITT-FALSE

1021

FFFF

0000

false

false

CRC16/X25

1021

FFFF

FFFF

true

true

CRC16/XMODEM

1021

0000

0000

false

false

CRC16/DNP

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

3D65

0000

FFFF

true

true

CRC32

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

04C11DB7

FFFFFFFF

FFFFFFFF

true

true

CRC32/MPEG-2

04C11DB7

FFFFFFFF

00000000

false

false

说明:

  • 多项式公式与多项式是对应的,生成多项式的最高位固定的1,故在简记式中忽略最高位1了

  • 初始值是给CRC计算一个初始值,即初始化与输入数据进行异或;

  • 结果异或值是把计算结果再异或某一个值;这么做的目的是防止全0数据的CRC一直为0。

  • 输入数据反转是指输入数据以字节为单位按位逆序处理;

  • 输出数据反转是指CRC计算结果整体按位逆序处理;

CRC算法的本质是将输入数据对除数(包括最高位的1的多项式,如CRC16/CCITT,除数即为0x11021)做模二运算求余数,余数即为CRC值;

CRC16通用算法

quint16 CRC_Normal::calculate_crc16(
    quint16 wCRCin,  //初始值
    quint16 wCPoly,  //多项式
    quint16 wResultXOR,  //结果异或值
    bool input_invert,   //输入反转
    bool ouput_invert,   //输出反转
    const char *puchMsg, //输入数据
    int usDataLen)       //输入数据长度
{
    quint8 wChar = 0;
    while (usDataLen--)
    {
        wChar = *(puchMsg++);
        if(input_invert)//输入值反转
        {
            quint8 temp_char = wChar;
            wChar=0;
            for(int i=0;i<8;++i)
            {
                if(temp_char&0x01)
                    wChar|=0x01<<(7-i);
                temp_char>>=1;
            }
        }
        wCRCin ^= (wChar << 8);
        /*以uint8输入,wCRCin的低8bit for循环后,再与输入的uint8[1]左移8bit后异或
        与wCRCin的低8bit与uint8[1]异或后,再for循环的值相同(即以uint16输入,即uint8[1]一直参与到除法求余运算中)
        因为从每个wCRCin的低8bit每个bit考虑,两者的操作只有异或先后顺序变更,其他一样。 
        以uint8输入 循环计算,即除法运算时被除数不断向末端移动
        wCRCin也可以理解为除法运算时每次运算的余数*/
        for (int i = 0; i < 8; i++)
        {
            if (wCRCin & 0x8000)
                /* 最高位为1,即被除数可以除以除数,后续bit需要对wCPol异或求余数 */
                wCRCin = (wCRCin << 1) ^ wCPoly;
            else
                wCRCin = wCRCin << 1;
        }
    }
    if(ouput_invert)
    {
        quint16 temp_short = wCRCin;
        wCRCin=0;
        for(int i=0;i<16;++i)
        {
            if(temp_short&0x01)
                wCRCin|=0x01<<(15-i);
            temp_short>>=1;
        }
    }
    return (wCRCin^wResultXOR);
}

CRC32/MPEG-2算法实现如下,其他算法类似

unsigned int CRC32_MPEG2(unsigned char *data, unsigned int datalen)
{
        unsigned int wCRCin = 0xFFFFFFFF;
        unsigned int wCPoly = 0x04C11DB7;
        unsigned char wChar = 0;
        int i = 0;
        while (datalen--) {
                wChar = *(data++);
                wCRCin ^= (wChar<<24);
                for (i = 0; i < 8; i++) {
                        if (wCRCin & 0x80000000)
                                wCRCin = (wCRCin << 1) ^ wCPoly;
                        else
                                wCRCin = wCRCin << 1;
                }
        }
        return wCRCin;
}

Reference

CRC-16原理及通用的16位CRC校验算法代码_crc16校验-优快云博客

【科普向】谁都能看懂的CRC(循环冗余校验)原理_crc原理-优快云博客

史上解释CRC最清楚的文章

CRC在线计算

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值