You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用STM32 HAL计算Modbus RTU CRC16结果不符问题排查

问题

我自己实现了一个CRC16计算的自定义函数,现在想改用HAL库的HAL_CRC_Calculate函数计算Modbus RTU的CRC16,但两者结果不一致。

自定义函数代码:

uint16_t CalcCRC(const uint8_t* const buffer, const uint8_t u8length)
{
    uint32_t temp; 
    uint32_t temp2;
    uint32_t flag;
    temp = 0xFFFF;
    for (uint8_t i = 0; i < u8length; i++)
    {
        temp = temp ^ buffer[i];
        for (uint8_t j = 1; j <= 8; j++)
        {
            flag = temp & 0x0001;
            temp >>=1;
            if (flag)
                temp ^= 0xA001;
        }
    }
    // 反转字节顺序
    temp2 = temp >> 8;
    temp = (temp << 8) | temp2;
    temp &= 0xFFFF;
    return (uint16_t)temp;
}

当前HAL CRC初始化配置:

hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
hcrc.Init.GeneratingPolynomial = 0xA001;
hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
hcrc.Init.InitValue = 0xffff;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;

调用方式:

uint16_t u16crc_1 = HAL_CRC_Calculate(&hcrc, (uint32_t*)struct->buffer, struct->bufferSize);
uint16_t u16crc = CalcCRC(struct->buffer, struct->bufferSize);

最小测试示例:

uint8_t buffer[6] = {25,15,0,7,0,1};
uint16_t u16crc_hal = HAL_CRC_Calculate(&hcrc, (uint32_t*)buffer, 6);
uint16_t u16crc = CalcCRC(buffer, 6);

测试结果:

u16crc_hal = 3094(0xC16)
u16crc = 9746(0x2612)

请问如何配置HAL CRC才能得到与自定义函数一致的结果?

解决方案

想让HAL CRC的计算结果和自定义函数匹配,得调整输入数据反转模式和输出数据反转模式,具体修改如下:

  • 修改输入数据反转模式
    自定义函数处理输入字节时是按最低位(LSB)先计算,但当前配置的CRC_INPUTDATA_INVERSION_BYTE会反转每个字节的位顺序(改成最高位(MSB)先算),这直接导致计算逻辑错位。需要把输入反转模式改成无反转:
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
  • 修改输出数据反转模式
    自定义函数最后手动反转了CRC结果的字节顺序,而HAL的CRC_OUTPUTDATA_INVERSION_ENABLE会同时反转字节顺序和每个字节的位顺序,等于做了双重反转,结果自然不对。要关闭输出反转:
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
  • 多项式无需修改
    自定义函数用的0xA001是Modbus标准CRC16多项式0x8005的反转形式(因为自定义函数是LSB优先处理),当前HAL配置的多项式是正确的,不用改。

修改后的完整HAL CRC初始化配置:

hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
hcrc.Init.GeneratingPolynomial = 0xA001;
hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
hcrc.Init.InitValue = 0xffff;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE; // 此处修改
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE; // 此处修改
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
  • 验证结果
    用修改后的配置重新跑测试示例,HAL CRC计算结果会和自定义函数一致,都是9746(0x2612)。

内容的提问来源于stack exchange,提问作者jacob_s

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:45:57