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

STM32启用RCC外设时钟后,如何正确实现2时钟周期延迟?

STM32外设时钟使能后2时钟周期延迟的正确实现

先明确背景:根据《RM0454 STM32G0x0参考手册》5.2.16节的说明,外设时钟使能位带有同步机制以消除毛刺,设置使能位后必须等待2个对应总线的时钟周期(挂载AHB的外设等2个AHB周期,挂载APB的外设等2个APB周期),外设时钟才会真正激活。STM32L0的HAL驱动注释也明确了这一要求。

下面两种实现方式都是正确的,只是适用场景不同:

示例1:读取RCC外设时钟使能寄存器

RCC->AHB1ENR |= (1 << RCC_AHB1ENR_GPIOAEN_Pos);
  
// do two dummy reads after enabling the peripheral clock, as per the errata
volatile uint32_t dummy;
dummy = RCC->AHB1ENR;
dummy = RCC->AHB1ENR;
  • 有效性说明:RCC的时钟使能寄存器大多挂载在AHB总线上,两次volatile读取会强制CPU执行两次总线访问,每次访问至少占用1个AHB时钟周期,刚好满足2个周期的延迟要求。如果是APB外设,读取对应的APB使能寄存器(比如RCC->APB1ENR),两次读取也能保证2个APB周期的延迟——因为APB总线的访问响应会对齐自身时钟。
  • 优势:代码简洁,不依赖其他外设,通用性强,无需考虑外设是否存在于目标芯片。
  • 适用场景:大多数常规开发场景,尤其是需要跨芯片移植的代码。

示例2:读取对应总线的外设寄存器

void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles)
{
    volatile uint32_t unused __attribute__((unused));
    if (bus == BUS_AHB) {
        while (cycles--)
            unused = STM32_DMA1_REGS->isr;
    } else { /* APB */
        while (cycles--)
            unused = STM32_USART_BRR(STM32_USART1_BASE);
    }
}
  • 有效性说明:直接读取挂载在目标总线上的外设寄存器,每次读取会消耗1个对应总线的时钟周期,循环2次就能精准匹配要求的延迟。比如当APB总线是AHB分频得到时,这种方式能确保延迟的是APB周期,而非AHB周期。
  • 优势:延迟精度更高,完全匹配目标总线的时钟,不会因总线分频关系出现偏差。
  • 注意事项:必须选择安全的只读寄存器(比如状态寄存器、波特率寄存器这类读取后不会改变硬件状态的寄存器),同时要确保目标外设在所用芯片上存在,避免移植时出现问题。
  • 适用场景:对时序要求极高的场景,或者总线分频逻辑复杂的系统。

总结

  • 追求简洁通用优先选择示例1;
  • 需要精准匹配总线周期时选择示例2。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 10:11:16