目前共有6篇帖子。 字體大小:較小 - 100% (默認)▼  內容轉換:不轉換▼
 
點擊 回復
27 5
C语言纯软件计算任意多项式CRC7、CRC8、CRC16和CRC32的代码
一派掌門 二十級
1樓 發表于:2026-1-20 13:35
/* CRC(循环冗余校验)在线计算: http://www.ip33.com/crc.html */
// 初始值INIT=0, 结果异或值XOROUT=0, 输入数据不反转, 输出数据不反转
#include <stdint.h>
#include <stdio.h>
#include <string.h>
 
#define POLYNOMIAL_CRC7 0x89ul
#define POLYNOMIAL_CRC8 0x107ul
#define POLYNOMIAL_CRC16 0x11021ul
#define POLYNOMIAL_CRC32 0x104c11db7ull
 
/* 计算CRC7校验码 */
uint8_t calc_crc7(const void *data, int len)
{
    const uint8_t *p = data;
    int i, j;
    uint16_t temp = 0;
 
    if (len != 0)
        temp = p[0] << 8;
 
    for (i = 1; i <= len; i++)
    {
        if (i != len)
            temp |= p[i];
        for (j = 0; j < 8; j++)
        {
            if (temp & 0x8000)
                temp ^= POLYNOMIAL_CRC7 << 8;
            temp <<= 1;
        }
    }
    return temp >> 9;
}
 
/* 计算CRC8校验码 */
uint8_t calc_crc8(const void *data, int len)
{
    const uint8_t *p = data;
    int i, j;
    uint16_t temp = 0;
 
    if (len != 0)
        temp = p[0] << 8;
 
    for (i = 1; i <= len; i++)
    {
        if (i != len)
            temp |= p[i];
        for (j = 0; j < 8; j++)
        {
            if (temp & 0x8000)
                temp ^= POLYNOMIAL_CRC8 << 7;
            temp <<= 1;
        }
    }
    return temp >> 8;
}
 
/* 计算CRC16校验码 */
uint16_t calc_crc16(const void *data, int len)
{
    const uint8_t *p = data;
    int i, j;
    uint32_t temp = 0;
 
    if (len & 1)
    {
        printf("%s: data size %d is odd!\n", __FUNCTION__, len);
        len--; // 不允许出现奇数长度
    }
    if (len != 0)
        temp = (p[0] << 24) | (p[1] << 16); // 填充前二分之一
    if (len > 2)
        temp |= p[2] << 8; // 填充到四分之三
 
    for (i = 3; i <= len + 2; i++)
    {
        if (i < len)
            temp |= p[i]; // 每次都填充最后四分之一的空间
        
        // 从左数第0~7位计算到左数第16~23位
        // 当j=0时是从左数第0位计算到第16位, 共计17位
        // 当j=1时是从左数第1位计算到第17位, 共计17位
        // ...
        // 当j=7时是从左数第7位计算到第23位, 共计17位
        for (j = 0; j < 8; j++)
        {
            if (temp & 0x80000000)
                temp ^= POLYNOMIAL_CRC16 << 15;
            temp <<= 1;
        }
    }
    return temp >> 16;
}
 
/* 计算CRC32校验码 */
uint32_t calc_crc32(const void *data, int len)
{
    const uint8_t *p = data;
    int i, j;
    uint64_t temp = 0;
 
    if (len & 3)
    {
        printf("%s: data size %d is not a multiple of 4\n", __FUNCTION__, len);
        len -= (len & 3);
    }
    if (len != 0)
        temp = ((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) | ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32); // 填充前二分之一
    if (len > 6)
        temp |= ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) | ((uint64_t)p[6] << 8); // 填充到八分之七
 
    for (i = 7; i <= len + 6; i++)
    {
        if (i < len)
            temp |= p[i]; // 每次都填充最后八分之一的空间
        
        // 从左数第0~7位计算到左数第32~39位
        // 当j=0时是从左数第0位计算到第32位, 共计33位
        // 当j=1时是从左数第1位计算到第33位, 共计33位
        // ...
        // 当j=7时是从左数第7位计算到第39位, 共计33位
        for (j = 0; j < 8; j++)
        {
            if (temp & 0x8000000000000000)
                temp ^= POLYNOMIAL_CRC32 << 31;
            temp <<= 1;
        }
    }
    return temp >> 32;
}
 
void main()
{
    char *str = "https://zh.purasbar.com/";
    int i, n;
 
    n = strlen(str);
    for (i = 0; i <= n; i += 4)
        printf("len=%d, crc7=0x%02x, crc8=0x%02x, crc16=0x%04x, crc32=0x%08x\n", i, calc_crc7(str, i), calc_crc8(str, i), calc_crc16(str, i), calc_crc32(str, i));
}
一派掌門 二十級
2樓 發表于:2026-1-20 13:35
程序运行结果:
len=0, crc7=0x00, crc8=0x00, crc16=0x0000, crc32=0x00000000
len=4, crc7=0x49, crc8=0x88, crc16=0x62d3, crc32=0x41e278d5
len=8, crc7=0x35, crc8=0x4f, crc16=0x90e6, crc32=0xe83f2f79
len=12, crc7=0x50, crc8=0x5c, crc16=0x9764, crc32=0x7392a791
len=16, crc7=0x7b, crc8=0x67, crc16=0xeeae, crc32=0x8bb08019
len=20, crc7=0x21, crc8=0xa2, crc16=0x335b, crc32=0xa70b55c8
len=24, crc7=0x3d, crc8=0xef, crc16=0xc4a5, crc32=0x20087a6a
————————————————
版权声明:本文为CSDN博主「巨大八爪鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ZLK1214/article/details/157174177
 
一派掌門 二十級
3樓 發表于:2026-1-20 13:35
四个计算函数长得非常像,就只是里面的数字不一样。
 
一派掌門 二十級
5樓 發表于:2026-1-20 14:13
#include <stdint.h>
#include <stdio.h>
#include <string.h>
 
#define INIT_CRC32 0xffffffffull
#define POLYNOMIAL_CRC32 0x104c11db7ull
 
uint8_t invert(uint8_t data)
{
    int i;
    uint8_t result = 0;
 
    for (i = 0; i < 8; i++)
    {
        result <<= 1;
        if (data & 1)
            result |= 1;
        data >>= 1;
    }
    return result;
}
 
uint32_t invert32(uint32_t data)
{
    uint32_t result;
 
    result = invert((data >> 24) & 0xff);
    result |= invert((data >> 16) & 0xff) << 8;
    result |= invert((data >> 8) & 0xff) << 16;
    result |= invert(data & 0xff) << 24;
    return result;
}
 
/* 计算CRC32校验码(初始值0xffffffff、结果异或值0xffffffff、输入数据反转、输出数据反转) */
uint32_t calc_crc32_inv(const void *data, int len)
{
    const uint8_t *p = data;
    int i, j;
    uint64_t temp = INIT_CRC32 << 32;
 
    if (len & 3)
    {
        printf("%s: data size %d is not a multiple of 4\n", __FUNCTION__, len);
        len -= (len & 3);
    }
    if (len != 0)
        temp ^= ((uint64_t)invert(p[0]) << 56) | ((uint64_t)invert(p[1]) << 48) | ((uint64_t)invert(p[2]) << 40) | ((uint64_t)invert(p[3]) << 32); // 填充前二分之一
    if (len > 6)
        temp |= ((uint64_t)invert(p[4]) << 24) | ((uint64_t)invert(p[5]) << 16) | ((uint64_t)invert(p[6]) << 8); // 填充到八分之七
 
    for (i = 7; i <= len + 6; i++)
    {
        if (i < len)
            temp |= invert(p[i]); // 每次都填充最后八分之一的空间
        
        // 从左数第0~7位计算到左数第32~39位
        // 当j=0时是从左数第0位计算到第32位, 共计33位
        // 当j=1时是从左数第1位计算到第33位, 共计33位
        // ...
        // 当j=7时是从左数第7位计算到第39位, 共计33位
        for (j = 0; j < 8; j++)
        {
            if (temp & 0x8000000000000000)
                temp ^= POLYNOMIAL_CRC32 << 31;
            temp <<= 1;
        }
    }
    return invert32(temp >> 32) ^ 0xffffffff;
}
 
void main()
{
    char *str = "https://zh.purasbar.com/";
    int i, n;
 
    n = strlen(str);
    for (i = 0; i <= n; i += 4)
        printf("len=%d, crc32_inv=0x%08x\n", i, calc_crc32_inv(str, i));

}


程序运行结果:
len=0, crc32_inv=0x00000000
len=4, crc32_inv=0x97780db2
len=8, crc32_inv=0xfed15547
len=12, crc32_inv=0x9692daf6
len=16, crc32_inv=0xe6326e98
len=20, crc32_inv=0xa6056b65
len=24, crc32_inv=0x3a66f237
————————————————
版权声明:本文为CSDN博主「巨大八爪鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ZLK1214/article/details/157174177

 
一派掌門 二十級
6樓 發表于:2026-1-20 15:21
有的单片机不支持uint64_t类型,无法运行calc_crc32函数和calc_crc32_inv函数。

注意到
if (temp & 0x8000000000000000)
    temp ^= POLYNOMIAL_CRC32 << 31;
temp <<= 1;
也就是
if (temp & 0x8000000000000000)
{
    temp ^= POLYNOMIAL_CRC32 << 31;
    temp <<= 1;
}
else
    temp <<= 1;
相当于
if (temp & 0x8000000000000000)
{
    temp <<= 1;
    temp ^= POLYNOMIAL_CRC32 << 32;
}
else
    temp <<= 1;
这样的话,我们就可以把一个uint64_t temp变量拆成两个uint32_t变量,使calc_crc32函数和calc_crc32_inv函数可以在不支持uint64_t类型的平台上运行。
————————————————
版权声明:本文为CSDN博主「巨大八爪鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ZLK1214/article/details/157174177
 
一派掌門 二十級
7樓 發表于:2026-1-20 15:21
#include <stdint.h>
#include <stdio.h>
#include <string.h>
 
#define POLYNOMIAL_CRC32 0x4c11db7
 
/* 计算CRC32校验码 */
uint32_t calc_crc32(const void *data, int len)
{
    const uint8_t *p = data;
    int i, j;
    uint32_t temp = 0;
    uint32_t temp2 = 0;
    uint32_t msb;
 
    // 填充前二分之一
    if (len > 0)
        temp |= p[0] << 24;
    if (len > 1)
        temp |= p[1] << 16;
    if (len > 2)
        temp |= p[2] << 8;
    if (len > 3)
        temp |= p[3];
 
    // 填充到八分之七
    if (len > 4)
        temp2 |= p[4] << 24;
    if (len > 5)
        temp2 |= p[5] << 16;
    if (len > 6)
        temp2 |= p[6] << 8;
 
    for (i = 7; i <= len + 6; i++)
    {
        if (i < len)
            temp2 |= p[i]; // 每次都填充最后八分之一的空间
        
        // 从左数第0~7位计算到左数第32~39位
        // 当j=0时是从左数第0位计算到第32位, 共计33位
        // 当j=1时是从左数第1位计算到第33位, 共计33位
        // ...
        // 当j=7时是从左数第7位计算到第39位, 共计33位
        for (j = 0; j < 8; j++)
        {
            msb = (temp & 0x80000000);
            
            temp <<= 1;
            if (temp2 & 0x80000000)
                temp |= 1;
            temp2 <<= 1;
 
            if (msb)
                temp ^= POLYNOMIAL_CRC32;
        }
    }
    return temp;
}
 
uint8_t invert(uint8_t data)
{
    int i;
    uint8_t result = 0;
 
    for (i = 0; i < 8; i++)
    {
        result <<= 1;
        if (data & 1)
            result |= 1;
        data >>= 1;
    }
    return result;
}
 
uint32_t invert32(uint32_t data)
{
    uint32_t result;
 
    result = invert((data >> 24) & 0xff);
    result |= invert((data >> 16) & 0xff) << 8;
    result |= invert((data >> 8) & 0xff) << 16;
    result |= invert(data & 0xff) << 24;
    return result;
}
 
/* 计算CRC32校验码(初始值0xffffffff、结果异或值0xffffffff、输入数据反转、输出数据反转) */
uint32_t calc_crc32_inv(const void *data, int len)
{
    const uint8_t *p = data;
    int i, j;
    uint32_t temp = 0xffffffff;
    uint32_t temp2 = 0;
    uint32_t msb;
 
    // 填充前二分之一
    if (len > 0)
        temp ^= invert(p[0]) << 24;
    if (len > 1)
        temp ^= invert(p[1]) << 16;
    if (len > 2)
        temp ^= invert(p[2]) << 8;
    if (len > 3)
        temp ^= invert(p[3]);
 
    // 填充到八分之七
    if (len > 4)
        temp2 |= invert(p[4]) << 24;
    if (len > 5)
        temp2 |= invert(p[5]) << 16;
    if (len > 6)
        temp2 |= invert(p[6]) << 8;
 
    for (i = 7; i <= len + 6; i++)
    {
        if (i < len)
            temp2 |= invert(p[i]); // 每次都填充最后八分之一的空间
        
        // 从左数第0~7位计算到左数第32~39位
        // 当j=0时是从左数第0位计算到第32位, 共计33位
        // 当j=1时是从左数第1位计算到第33位, 共计33位
        // ...
        // 当j=7时是从左数第7位计算到第39位, 共计33位
        for (j = 0; j < 8; j++)
        {
            msb = (temp & 0x80000000);
            
            temp <<= 1;
            if (temp2 & 0x80000000)
                temp |= 1;
            temp2 <<= 1;
 
            if (msb)
                temp ^= POLYNOMIAL_CRC32;
        }
    }
    return invert32(temp) ^ 0xffffffff;
}
 
void main()
{
    char *str = "https://zh.purasbar.com/";
    int i, n;
 
    n = strlen(str);
    for (i = 0; i <= n; i++)
        printf("len=%d, crc32=0x%08x, crc32_inv=0x%08x\n", i, calc_crc32(str, i), calc_crc32_inv(str, i));

}


程序运行结果:
len=0, crc32=0x00000000, crc32_inv=0x00000000
len=1, crc32=0x8aad2b2f, crc32_inv=0x916b06e7
len=2, crc32=0x181d7203, crc32_inv=0xbb954675
len=3, crc32=0x84db5ef3, crc32_inv=0xa5be4a5d
len=4, crc32=0x41e278d5, crc32_inv=0x97780db2
len=5, crc32=0x3fc883fe, crc32_inv=0x3ef665a6
len=6, crc32=0xdf46956b, crc32_inv=0x2b85c687
len=7, crc32=0xcf2d9609, crc32_inv=0x0a244191
len=8, crc32=0xe83f2f79, crc32_inv=0xfed15547
len=9, crc32=0x13b079f0, crc32_inv=0x8a9472c9
len=10, crc32=0x7b862686, crc32_inv=0x7359e881
len=11, crc32=0xe974466c, crc32_inv=0x9418081c
len=12, crc32=0x7392a791, crc32_inv=0x9692daf6
len=13, crc32=0x8821dcb2, crc32_inv=0xa625afcd
len=14, crc32=0x87ee99df, crc32_inv=0x897a643f
len=15, crc32=0x31b6b4cb, crc32_inv=0x5e58e91a
len=16, crc32=0x8bb08019, crc32_inv=0xe6326e98
len=17, crc32=0x57e0cf76, crc32_inv=0x8f8cc6e1
len=18, crc32=0x2e7b5622, crc32_inv=0x3f35e06b
len=19, crc32=0x36cd1263, crc32_inv=0xb65672ad
len=20, crc32=0xa70b55c8, crc32_inv=0xa6056b65
len=21, crc32=0x45db2e45, crc32_inv=0x3bc74fd3
len=22, crc32=0x6c872536, crc32_inv=0x10eed765
len=23, crc32=0x83e42bb7, crc32_inv=0xdcc98968
len=24, crc32=0x20087a6a, crc32_inv=0x3a66f237
————————————————
版权声明:本文为CSDN博主「巨大八爪鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ZLK1214/article/details/157174177

 

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
(快捷鍵:Ctrl+Enter)
 

本帖信息

點擊數:27 回複數:5
評論數: ?
作者:巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2026-1-20 15:21
 
©2010-2026 Purasbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。