CRC校验

2023-06-10

标准CRC生成多项式
名称 生成多项式 简记式 标准引用
CRC-4 $x^4 + x + 1$ 3 ITU G.704
CRC-8 $x^8 + x^5 + x^4 + 1$ 0x31  
CRC-8 $x^8 + x^2 + x + 1$ 0x07  
CRC-8 $x^8 + x^6 + x^4 + x^3 + x^2 + x$ 0x5E  
CRC-12 $x^{12} + x^{11} + x^3 + x + 1$ 0x80F  
CRC-16 $x^{16} + x^{15} + x^2 + 1$ 0x8005 IBM SDLC
CRC16-CCITT $x^{12} + x^{11} + x^3 + x + 1$ 0x1021 ISO HDLC, ITU X.25,,V.34/V.41/V.42, PPP-FCS
CRC-32 $x^{32} + x^{26} + x^{23} + … + x^2 + x + 1$ 0x04C11DB7 ZIP, RAR, IEEE 802 LAN/FDDI, IEEE 1394, PPP-FCS
CRC-32c $x^{32} + x^{28} + x^{27} + … + x^8 + x^6 + 1$ 0x1EDC6F41 SCTP
CRC计算方法

常用查表法和计算法。

计算法步骤如下:

/// 计算法
1)、预置116位的寄存器为十六进制FFFF(即全为1),称此寄存器为CRC寄存器;
2)、把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低8位相异或,把结果放于CRC寄存器,高八位数据不变;
3)、把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位;
4)、如果移出位为0:重复第3步(再次右移一位);如果移出位为1CRC寄存器与多项式A0011010 0000 0000 0001)进行异或;
5)、重复步骤34,直到右移8次,这样整个8位数据全部进行了处理;
6)、重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;
7)、将该通讯信息帧所有字节按上述步骤计算完成后,得到的16CRC寄存器的高、低字节进行交换;
8)、最后得到的CRC寄存器内容即为:CRC码。
    
/// 以上计算步骤中的多项式A001是8005按位翻转后的结果。
/// byte[] data = Encoding.Unicode.GetBytes("今天天气很好");

/// GetCrc16(data, 0x1021, true) -- CRC-16/MCRF4XX
/// GetCrc16(data, 0x1021, false) -- CRC-16/XMODEM
/// GetCrc16(data, 0x8005, true) -- CRC-16/MODBUS
/// GetCrc16(data, 0x8005, false) -- CRC-16/BUYPASS

/// Console.WriteLine($"crc1 = 0x{GetCrc16(data, 0x1021, false):X4}, crc2 = 0x{NewLife.SecurityHelper.Crc16(data):X4}"); crc1 = 0x5DC1, crc2 = 0x5DC1

/// Console.WriteLine($"crc1 = 0x{GetCrc16(data, 0x8005, true):X4}, crc2 = 0x{NewLife.Security.Crc16.Compute(stream, -1):X4}"); crc1 = 0xD63B, crc2 = 0xD63B


/// CRC-16
UInt16 GetCrc16(byte[] data, UInt16 Poly/*多项式*/, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
    UInt16 crc = 0xFFFF;
    if (isReverse)
    {
        /// 逆序多项式
        BitVector32 bits = new BitVector32((Int32)Poly);
        BitVector32 reverse_bits = new BitVector32();
        for (int i = 0; i < 32; i++)
        {
            reverse_bits[1 << (31 - i)] = bits[1 << i];
        }
        Poly = (UInt16)((reverse_bits.Data >> 16) & 0xffff);


        crc = 0xFFFF;
        for (UInt16 i = 0; i < data.Length; i++)
        {
            crc ^= data[i];
            for (UInt16 j = 0; j < 8; j++)
            {
                if ((crc & 0x1) != 0)
                {
                    crc = (UInt16)((crc >> 1) ^ Poly);
                }
                else
                {
                    crc = (UInt16)(crc >> 1);
                }
            }
        }
    }
    else
    {
        crc ^= crc;
        for (UInt16 i = 0; i < data.Length; i++)
        {
            crc ^= (UInt16)(data[i] << 8);
            for (UInt16 j = 0; j < 8; j++)
            {
                if ((crc & 0x8000) != 0)
                {
                    crc = (UInt16)((crc << 1) ^ Poly);
                }
                else
                {
                    crc = (UInt16)(crc << 1);
                }
            }
        }
    }
    return crc;
}
/// byte[] data = Encoding.Unicode.GetBytes("今天天气很好");

/// GetCrc32(data, 0x04C11DB7, true) -- CRC-32
/// GetCrc32(data, 0x04C11DB7, false) -- CRC-32/POSIX
/// GetCrc32(data, 0x1EDC6F41, true) -- CRC-32C

/// Console.WriteLine($"crc1 = 0x{GetCrc32(data, 0x04C11DB7, true):X8}, crc2 = 0x{NewLife.Security.Crc32.Compute(data):X8}"); crc1 = 0x7B1B0DAA, crc2 = 0x7B1B0DAA


/// crc32
UInt32 GetCrc32(byte[] data, UInt32 Poly/*多项式*/, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
    UInt32 crc = 0xFFFFFFFF;
    if (isReverse)
    {
        /// 逆序多项式
        BitVector32 bits = new BitVector32((Int32)Poly);
        BitVector32 reverse_bits = new BitVector32();
        for (int i = 0; i < 32; i++)
        {
            reverse_bits[1 << (31 - i)] = bits[1 << i];
        }
        Poly = (UInt32)reverse_bits.Data;

        crc = 0xFFFFFFFF;
        for (UInt32 i = 0; i < data.Length; i++)
        {
            crc ^= data[i];
            for (UInt32 j = 0; j < 8; j++)
            {
                if ((crc & 0x1) != 0)
                {
                    crc = (UInt32)((crc >> 1) ^ Poly);
                }
                else
                {
                    crc = (UInt32)(crc >> 1);
                }
            }
        }        
    }
    else
    {
        crc ^= crc;
        for (UInt32 i = 0; i < data.Length; i++)
        {
            crc ^= (UInt32)(data[i] << 24);
            for (UInt32 j = 0; j < 8; j++)
            {
                if ((crc & 0x80000000) != 0)
                {
                    crc = (UInt32)((crc << 1) ^ Poly);
                }
                else
                {
                    crc = (UInt32)(crc << 1);
                }
            }
        }
    }
    return crc ^ 0xFFFFFFFF;
}

查表法步骤:

/// 查表法
查表法是将移位异或的计算结果做成了一个表,就是将0~256放入一个长度为16位的寄存器中的低八位,高八位填充0,然后将该寄存器与多项式0XA001按照上述34步骤,直到八位全部移出,最后寄存器中的值就是表格中的数据,高八位、低八位分别单独一个表。
/// CRC-16
0x8005 = 1000 0000 0000 0101B

0xA001 = 1010 0000 0000 0001B
    
1、对比两个二进制高低位正好是完全倒序的,CRC校验分为正向校验与反向校验。正向校验高位在左,反向校验低位在左。
2、比如正向CRC校验的数据为0xAF5D=1010 1111 0101 1101B0x8005异或时应该是0xAF5D^0x8005,而要使用0xA001与数据进行校验也应该使0xAF5D高低位换顺序为0xBAF5=1011 1010 1111 0101B
3正向校验使用左移位,反向校验使用右移位,其实原理是一样的,得看校验的数据高低位顺序
CRC生成表方法
/// crc16
UInt16[] GenerateCRC16Table(UInt16 Poly/*多项式*/, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
    UInt16[] crc_table = new UInt16[256];


    if (isReverse)
    {
        /// 逆序多项式
        BitVector32 bits = new BitVector32((Int32)Poly);
        BitVector32 reverse_bits = new BitVector32();
        for (int i = 0; i < 32; i++)
        {
            reverse_bits[1 << (31 - i)] = bits[1 << i];
        }
        Poly = (UInt16)((reverse_bits.Data >> 16) & 0xffff);
    }

    Parallel.For(0, 256, number =>
    {
        UInt16 crc;

        if (isReverse)
        {
            crc = (UInt16)number;
            for (UInt16 i = 0; i < 8; i++)
            {
                if ((crc & 0x1) != 0)
                {
                    crc = (UInt16)((crc >> 1) ^ Poly);
                }
                else
                {
                    crc = (UInt16)(crc >> 1);
                }
            }
        }
        else
        {
            crc = (UInt16)(number << 8);
            for (UInt16 i = 0; i < 8; i++)
            {
                if ((crc & 0x8000) != 0)
                {
                    crc = (UInt16)((crc << 1) ^ Poly);
                }
                else
                {
                    crc = (UInt16)(crc << 1);
                }
            }
        }

        crc_table[number] = crc;
    });

    return crc_table;
}
/// crc32
UInt32[] GenerateCRC32Table(UInt32 Poly/*多项式*/, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
    UInt32[] crc_table = new UInt32[256];

    if (isReverse)
    {
        /// 逆序多项式
        BitVector32 bits = new BitVector32((Int32)Poly);
        BitVector32 reverse_bits = new BitVector32();
        for (int i = 0; i < 32; i++)
        {
            reverse_bits[1 << (31 - i)] = bits[1 << i];
        }
        Poly = (UInt32)reverse_bits.Data;
    }

    Parallel.For(0, 256, number =>
    {
        UInt32 crc;

        if (isReverse)
        {
            crc = (UInt32)number;
            for (UInt32 i = 0; i < 8; i++)
            {
                if ((crc & 0x1) != 0)
                {
                    crc = (UInt32)((crc >> 1) ^ Poly);
                }
                else
                {
                    crc = (UInt32)(crc >> 1);
                }
            }
        }
        else
        {
            crc = (UInt32)(number << 24);
            for (UInt32 i = 0; i < 8; i++)
            {
                if ((crc & 0x80000000) != 0)
                {
                    crc = (UInt32)((crc << 1) ^ Poly);
                }
                else
                {
                    crc = (UInt32)(crc << 1);
                }
            }
        }

        crc_table[number] = crc;
    });

    return crc_table;
}
/// 测试代码
/// byte[] data = Encoding.Unicode.GetBytes("今天天气很好");
/// Stream stream = new MemoryStream(data);

/// Console.WriteLine($"GetCrc16(data, 0x1021, false) = 0x{GetCrc16(data, 0x1021, false):X4}.");
/// Console.WriteLine($"GetCrc16_Table(data, crc_2, false) = 0x{GetCrc16_Table(data, crc_2, false):X4}.");
/// Console.WriteLine($"NewLife.SecurityHelper.Crc16(data) = 0x{NewLife.SecurityHelper.Crc16(data):X4}.");

/// Console.WriteLine($"GetCrc16(data, 0x8005, true) = 0x{GetCrc16(data, 0x8005, true):X4}.");
/// Console.WriteLine($"GetCrc16_Table(data, crc_3, true) = 0x{GetCrc16_Table(data, crc_3, true):X4}.");
/// Console.WriteLine($"NewLife.Security.Crc16.ComputeModbus(data, 0, data.Length) = 0x{NewLife.Security.Crc16.ComputeModbus(data, 0, data.Length):X4}.");

/// 输出结果
/// GetCrc16(data, 0x1021, false) = 0x5DC1.
/// GetCrc16_Table(data, crc_2, false) = 0x5DC1.
/// NewLife.SecurityHelper.Crc16(data) = 0x5DC1.
/// GetCrc16(data, 0x8005, true) = 0xD63B.
/// GetCrc16_Table(data, crc_3, true) = 0xD63B.
/// NewLife.Security.Crc16.ComputeModbus(data, 0, data.Length) = 0xD63B.

UInt16 GetCrc16_Table(byte[] data, UInt16[] crc_table, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
    /// https://blog.csdn.net/weixin_44256803/article/details/111794445
    /// https://blog.csdn.net/qq_25814297/article/details/109402108
    UInt16 crc = 0xFFFF;

    if (isReverse)
    {
        for (UInt16 i = 0; i < data.Length; i++)
        {
            crc = (UInt16)((crc >> 8) ^ crc_table[(crc ^ data[i]) & 0xFF]);
        }
    }
    else
    {
        crc ^= crc;
        for (UInt16 i = 0; i < data.Length; i++)
        {
            crc = (UInt16)((crc << 8) ^ crc_table[(crc >> 8 ^ data[i]) & 0xFF]);
        }
    }

    return crc;
}
/// 测试代码
/// byte[] data = Encoding.Unicode.GetBytes("今天天气很好");
/// Stream stream = new MemoryStream(data);

/// UInt32[] crc32_1 = GenerateCRC32Table(0x04C11DB7, true);
/// Console.WriteLine($"GetCrc32(data, 0x04C11DB7, true) = 0x{GetCrc32(data, 0x04C11DB7, true):X4}.");
/// Console.WriteLine($"GetCrc32_Table(data, crc32_1, false) = 0x{GetCrc32_Table(data, crc32_1, true):X4}.");
/// Console.WriteLine($"NewLife.Security.Crc32.Compute(data, 0, data.Length) = 0x{NewLife.Security.Crc32.Compute(data, 0, data.Length):X4}.");

/// 输出结果
/// GetCrc32(data, 0x04C11DB7, true) = 0x7B1B0DAA.
/// GetCrc32_Table(data, crc32_1, false) = 0x7B1B0DAA.
/// NewLife.Security.Crc32.Compute(data, 0, data.Length) = 0x7B1B0DAA.

UInt32 GetCrc32_Table(byte[] data, UInt32[] crc_table, bool isReverse/*true:逆序 低位在左,高位在右,false:正序 高位在左,低位在右*/)
{
    UInt32 crc = 0xFFFFFFFF;

    if (isReverse)
    {
        for (UInt16 i = 0; i < data.Length; i++)
        {
            crc = (UInt32)((crc >> 8) ^ crc_table[(crc ^ data[i]) & 0xFF]);
        }
    }
    else
    {
        crc ^= crc;
        for (UInt16 i = 0; i < data.Length; i++)
        {
            crc = (UInt32)((crc << 8) ^ crc_table[(crc >> 24 ^ data[i]) & 0xFF]);
        }
    }

    return crc ^ 0xFFFFFFFF;
}

crc算法可灵活设置Init初始化值、Poly多项式值、RefIn/RefOut是否倒序、XorOut结果异或等参数计算出不同结果。后期如需计算其它类型crc,可参照CRC在线计算

CRC全套校验码生成函数源码(非查表)逐位运算法

CRC全套校验码生成函数源码(非查表)逐位运算法

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);
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;
}
点击查看评论

所有文章