C: CRC16,CRC32 计算代码

说明:CRC16/MODBUS ,CRC32 计算代码
推荐个在线CRC计算网站

http://www.ip33.com/crc.html

1:计算 CRC32 算法代码:

//计算CRC32的算法代码:
uint32_t crc32(uint8_t *data, uint32_t length)
{
    uint32_t crc = 0xFFFFFFFF;
    uint32_t table[256];

    // 生成CRC32查找表
    for (uint32_t i = 0; i < 256; i++)
    {
        uint32_t c = i;
        for (int j = 0; j < 8; j++)
        {
            if (c & 1)
            {
                c = 0xEDB88320 ^ (c >> 1);
            }
            else
            {
                c = c >> 1;
            }
        }
        table[i] = c;
    }

    // 计算CRC32
    for (uint32_t i = 0; i < length; i++)
    {
        crc = table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
    }

    return crc ^ 0xFFFFFFFF;
}


//测试代码
int main()
{
    uint8_t data[] = { 0x12, 0x34, 0x56, 0x78 };
    uint32_t crc = crc32(data, sizeof(data));

    printf("CRC32: 0x%08X
", crc);

    return 0;
}

//输出结果
CRC32: 0x4A090E98

2.计算 CRC16 算法代码 1:

/* CRC16 余式表 */
static uint16_t crctalbeabs[] =
{
    0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
    0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400
};

/*!
 *  功  能: CRC16校验
 *  param1: 指向要校验的数据的指针
 *  param2: 要校验的数据的长度
 *  retval: 校验所得到的值,uint16_t 类型
 *
 *  说  明: 本次CRC校验为查表法,多项式为 x16+x15+x2+1(0x8005),CRC的初始值为0xFFFF
 */
uint16_t Crc16_C(uint8_t *ptr, uint32_t len)
{
    uint16_t crc = 0xffff;
    uint32_t i;
    uint8_t ch;

    for (i = 0; i < len; i++)
    {
        ch = *ptr++;
        crc = crctalbeabs[(ch ^ crc) & 15] ^ (crc >> 4);
        crc = crctalbeabs[((ch >> 4) ^ crc) & 15] ^ (crc >> 4);
    }

    return crc;
}

//测试代码
int main() 
{
    uint8_t data[] = {0x12, 0x34, 0x56, 0x78};
    uint32_t crc = Crc16_C(data, sizeof(data));

    printf("CRC16: 0x%04X
", crc);

    return 0;
}

//输出结果
CRC16: 0x107B

3.计算 CRC16 算法代码 2:

#include <stdio.h>
#include <stdint.h>

static uint16_t yl_crc16(unsigned char *buffer, uint16_t len)
{
    uint16_t wcrc = 0XFFFF;         //16位crc寄存器预置
    uint8_t temp;
    uint16_t i = 0, j = 0;          //计数
    for (i = 0; i < len; i++)       //循环计算每个数据
    {
        temp = *buffer & 0X00FF;    //将八位数据与crc寄存器亦或
        buffer++;                   //指针地址增加,指向下个数据
        wcrc ^= temp;               //将数据存入crc寄存器
        for (j = 0; j < 8; j++)     //循环计算数据的
        {
            if (wcrc & 0X0001)      //判断右移出的是不是1,如果是1则与多项式进行异或。
            {
                wcrc >>= 1;         //先将数据右移一位
                wcrc ^= 0XA001;     //与上面的多项式进行异或
            }
            else                    //如果不是1,则直接移出
            {
                wcrc >>= 1;         //直接移出
            }
        }
    }

    return wcrc;
}

int main() 
{
    unsigned char data[] = {0x12, 0x34, 0x56, 0x78};
    int len = sizeof(data) / sizeof(data[0]);
    uint16_t crc = yl_crc16(data, len);
    printf("CRC16: 0x%04X
", crc);
    return 0;
}

//输出结果
CRC16: 0x107B