硬汉嵌入式论坛

 找回密码
 立即注册
搜索
查看: 59|回复: 4
收起左侧

[STM32H7] 硬件CRC配合REV指令实现Modbus CRC16极致优化

[复制链接]

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
123897
QQ
发表于 3 小时前 | 显示全部楼层 |阅读模式


之前一直使用的软件CRC,但程序里面调用太频繁了,所以准备优化下。

三种方案实测了性能比较

1、查表法

特点已经简单好用,性能算是软件方案里面不错的


[C] 纯文本查看 复制代码
uint16_t CRC16_Modbus(const uint8_t *_pBuf, uint16_t _usLen)
{

    uint8_t ucCRCHi = 0xFF; /* 高CRC字节初始化 */
    uint8_t ucCRCLo = 0xFF; /* 低CRC 字节初始化 */
    uint16_t usIndex;                /* CRC循环中的索引 */

    while (_usLen--)
   {
        usIndex = ucCRCHi ^ *_pBuf++; /* 计算CRC */        
        ucCRCHi = ucCRCLo ^ s_CRCHi[usIndex];
        ucCRCLo = s_CRCLo[usIndex];
    }

   return ((uint16_t)ucCRCHi << 8 | ucCRCLo);
}



2、硬件CRC + HAL库API实现

配置:
[C] 纯文本查看 复制代码
    /* 用于CRC16_Modbus替代  */
    crcHandle.Instance = CRC;
    crcHandle.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
    crcHandle.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
    crcHandle.Init.GeneratingPolynomial = 0x8005;
    crcHandle.Init.CRCLength = CRC_POLYLENGTH_16B;
    crcHandle.Init.InitValue = 0xffff;
    crcHandle.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
    crcHandle.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
    crcHandle.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
    if (HAL_CRC_Init(&crcHandle) != HAL_OK)
    {
        Error_Handler(__FILE__, __LINE__);
    }   


输出使用
[C] 纯文本查看 复制代码
uint16_t CRC16_Modbus(const uint8_t *_pBuf, uint16_t _usLen)
{
    uint8_t ucCRCHi = 0xFF; /* 高CRC字节初始化 */
    uint8_t ucCRCLo = 0xFF; /* 低CRC 字节初始化 */
    uint16_t usIndex;                /* CRC循环中的索引 */

   usIndex = HAL_CRC_Calculate(&crcHandle, (uint32_t *)_pBuf, _usLen);

   ucCRCLo = usIndex >> 8;
   ucCRCHi = usIndex & 0xFF;

   return ((uint16_t)ucCRCHi << 8 | ucCRCLo);
}


3、硬件CRC + REV指令

使用REV指令,将4个字节组合发给DR寄存器。

[C] 纯文本查看 复制代码
uint16_t CRC16_Modbus_HW(const uint8_t *_pBuf, uint16_t _usLen)
{
    uint32_t i;
    uint32_t n;

    CRC->CR |= CRC_CR_RESET;                        /* 加载 INIT=0xFFFF */

    if (((uint32_t)_pBuf & 3u) == 0u)               /* 4 字节对齐:LDR+REV 快速路径 */
    {
        const uint32_t *p32 = (const uint32_t *)_pBuf;
        n = _usLen / 4u;
        for (i = 0u; i < n; i++)
        {
            CRC->DR = __REV(*p32++);                /* 1×LDR + 1×REV */
        }
        i = 4u * n;
    }
    else                                            /* 非对齐:移位 OR 组包(HAL 等价,任何对齐安全) */
    {
        for (i = 0u; i < (_usLen / 4u); i++)
        {
            CRC->DR = ((uint32_t)_pBuf[4u*i]     << 24u) |
                      ((uint32_t)_pBuf[4u*i + 1] << 16u) |
                      ((uint32_t)_pBuf[4u*i + 2] << 8u)  |
                      ((uint32_t)_pBuf[4u*i + 3]);
        }
        i = 4u * i;
    }

    /* 公共尾部:1~3 字节,BYTES 格式写 DR 低 8 位 */
    while (_usLen > i)
    {
        *(__IO uint8_t *)(__IO void *)&CRC->DR = _pBuf[i];
        i++;
    }

    return (uint16_t)CRC->DR;
}


输出结果再用REV16切换高低字节

[C] 纯文本查看 复制代码
uint16_t CRC16_Modbus(const uint8_t *_pBuf, uint16_t _usLen)
{
   return __REV16(CRC16_Modbus_HW((const uint8_t *)_pBuf, _usLen));
}


4、实际测试性能比较


  软件CRC, 直接HAL
_usLen =16   CRC_ENABLE: cycles=315,   0. 79us
_usLen=131  CRC_ENABLE: cycles=1926, 4. 82us

  硬件CRC,直接HAL
_usLen =16  CRC_ENABLE:cycles=196, 0.49us
_usLen=131  CRC_ENABLE:cycles=570,  1.42us

  硬件CRC,  配合REV
_usLen =16  CRC_ENABLE:cycles=173,  0.43us
_usLen=131  CRC_ENABLE:cycles= 509, 1.27us



回复

使用道具 举报

13

主题

508

回帖

547

积分

金牌会员

积分
547
发表于 1 小时前 | 显示全部楼层
stm32的crc好像是crc32,在Modbus上用不了吧?只能用软件crc吧?
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
123897
QQ
 楼主| 发表于 1 小时前 | 显示全部楼层
fxyc87 发表于 2026-8-25 11:58
stm32的crc好像是crc32,在Modbus上用不了吧?只能用软件crc吧?

可以用,合理配置CRC参数就可以了。

就是楼主位那个配置
回复

使用道具 举报

4

主题

132

回帖

144

积分

初级会员

积分
144
发表于 1 小时前 | 显示全部楼层
有没有可能使用DMA处理进一步降低CPU的使用率
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
123897
QQ
 楼主| 发表于 半小时前 | 显示全部楼层
hance2000 发表于 2026-8-25 12:24
有没有可能使用DMA处理进一步降低CPU的使用率

没弄DMA,主要是数据长度一直是动态变化话的,DMA优势不好发挥出来。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-8-25 13:54 , Processed in 0.317850 second(s), 5 queries , File On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表