个人笔记:crc32(循环冗余校验)查表算法

本文详细介绍了循环冗余校验(CRC32)的基本原理,包括异或运算的性质,以及如何通过查表法进行快速计算。还讨论了在不同字节顺序下CRC32的计算方法,以及crc32_no_comp和crc32函数的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

个人理解,如有错误,可以指出
参考【科普向】谁都能看懂的CRC(循环冗余校验)原理
参考 CRC校验(2):CRC32查表法详解、代码实现和CRC反转

请添加图片描述
在这里插入图片描述

异或运算满足 :
【a^b=b^a,交换律】
【(a^b)^c=a^(b^c),结合律】
【0^a=a】
【a^1=~a,取反操作】

1字节(Byte),值区间[0,255]
对x属于[0,255]CRC32(x)有唯一对应的余数
可以先计算对应的 :
256CRC32(x)值
local const uint32_t crc_table[256] = {
tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
.......省略..........................................................
tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
};

在这里插入图片描述
从一个所有位都设置为1的32位校验和(0xffffffff)开始。这有助于在输入字符串为“0”字节时生成一个非零的输出值。
在循环结束后,将计算出的CRC值与0xffffffff进行异或运算(这与对CRC值进行二进制取反操作相同)。【a^1=~a,取反操作,0 xor 1 = 1,1 xor 1 = 0】

/* ========================================================================= */
# if __BYTE_ORDER == __LITTLE_ENDIAN
#  define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
# else
#  define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
# endif

uint32_t ZEXPORT crc32_no_comp(uint32_t crc, const Bytef *buf, uInt len)
{
    const uint32_t *tab = crc_table;
    const uint32_t *b =(const uint32_t *)buf;
    size_t rem_len;
#ifdef DYNAMIC_CRC_TABLE
    if (crc_table_empty)
      make_crc_table();
#endif
    crc = cpu_to_le32(crc);
    /* Align it */
    if (((long)b) & 3 && len) {
	 uint8_t *p = (uint8_t *)b;
	 do {
	      DO_CRC(*p++);
	 } while ((--len) && ((long)p)&3);
	 b = (uint32_t *)p;
    }

    rem_len = len & 3;
    len = len >> 2;
    for (--b; len; --len) {
	 /* load data 32 bits wide, xor data 32 bits wide. */
	 crc ^= *++b; /* use pre increment for speed */
	 DO_CRC(0);
	 DO_CRC(0);
	 DO_CRC(0);
	 DO_CRC(0);
    }
    len = rem_len;
    /* And the last few bytes */
    if (len) {
	 uint8_t *p = (uint8_t *)(b + 1) - 1;
	 do {
	      DO_CRC(*++p); /* use pre increment for speed */
	 } while (--len);
    }

    return le32_to_cpu(crc);
}
#undef DO_CRC

uint32_t ZEXPORT crc32 (uint32_t crc, const Bytef *p, uInt len)
{
     return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
}

在这里插入图片描述

在STM32中使用CRC16查表法进行计算的方法如下: ```c #include <stdint.h> // CRC16查表法计算函数 uint16_t CRC16_TableCalculate(uint8_t *data, uint8_t length) { uint16_t crc = 0xFFFF; uint16_t table\[256\] = { // CRC16查表法的表格数据 // ... }; for (int i = 0; i < length; i++) { crc = (crc >> 8) ^ table\[(crc ^ data\[i\]) & 0xFF\]; } return crc; } ``` 这段代码使用了一个256个元素的表格来存储CRC16的计算结果。在计算过程中,根据输入数据进行查表,从头查到尾得到最终的CRC校验值。这种方法相比直接计算方法,可以大大提高计算效率。 请注意,上述代码中的表格数据并未提供,你需要根据CRC16算法的多项式和初始值来生成对应的表格数据。具体的生成方法可以参考CRC16算法的实现文档或相关资料。 #### 引用[.reference_title] - *1* *3* [stm32 CRC-16校验代码,单片机ModBUS-CRC16校验](https://blog.youkuaiyun.com/Mark_md/article/details/108600959)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [嵌入式STM32学习笔记(7)——ModBus RTU CRC16校验](https://blog.youkuaiyun.com/abcvincent/article/details/104418838)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值