如何配置 STM32H7 硬件 CRC 以匹配 Python 中的 zlib CRC32

你可以配置 STM32 CRC32 外设以匹配 zlib 使用的 CRC32 算法(可在 Python 的 zlib 模块中使用):

根据 crccalc.com,zlib CRC32(那里称为 CRC-32/ISO-HDLC)使用 Init=0xFFFFFFFFXorOut=0xFFFFFFFF 和输入输出的逐字节反转。

在 STM32H7 上,你可以使用 HAL 配置 CRC 外设以匹配此设置:

crc_example.cpp
void Init_CRC32() {
    __HAL_RCC_CRC_CLK_ENABLE();
    // Reset CRC
    _hcrc.Instance = CRC;
    _hcrc.Init.DefaultPolynomialUse    = DEFAULT_POLYNOMIAL_ENABLE;
    _hcrc.Init.DefaultInitValueUse     = DEFAULT_INIT_VALUE_ENABLE;
    _hcrc.Init.InputDataInversionMode  = CRC_INPUTDATA_INVERSION_BYTE;
    _hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
    _hcrc.InputDataFormat              = CRC_INPUTDATA_FORMAT_BYTES;

    HAL_CRC_Init(&_hcrc);
}

uint32_t CalculateCRC32(void* data, size_t length)
{
    // Compute the CRC
    uint32_t crc_result = HAL_CRC_Calculate(&_hcrc, reinterpret_cast<uint32_t*>(data), length);

    // Invert to obtain ZLIB CRC32
    return crc_result ^ 0xFFFFFFFF;
}

以下测试代码可用于验证结果

crc_test.cpp
void TestCRC32() {
    uint32_t crc = CalculateCRC32((void*)"DEADBEEF", 8);
    printf("CRC32 of 'DEADBEEF': %08X", crc);

    // When testing, always include a non-divisible-by-4 number of bytes
    crc = CalculateCRC32((void*)"Hello, World!", 13);
    SendLogMessageF("CRC32 of 'Hello, World!': %08X", crc);
}

输出:

crc_test_output.txt
CRC32 of 'DEADBEEF': E24CEE98
CRC32 of 'Hello, World!': EC4AC3D0

等效 Python 代码

此 Python 代码非常简单,因为它使用内置的 zlib 模块:

zlib_crc32.py
import zlib

def calculate_crc32(data: bytes) -> int:
    return zlib.crc32(data)

print(f"CRC32 of 'Hello, World!': {calculate_crc32(b'Hello, World!'):08X}")
print(f"CRC32 of 'DEADBEEF': {calculate_crc32(b'DEADBEEF'):08X}")

输出:

zlib_crc32_output.txt
CRC32 of 'DEADBEEF': E24CEE98
CRC32 of 'Hello, World!': EC4AC3D0

你甚至可以内联执行:

zlib_crc32_inline.py
import zlib

print(f'{zlib.crc32(b"DEADBEEF"):08X}') # E24CEE98

Check out similar posts by category: Python, STM32