STM32 低功耗模式下的 DMA 外设保持策略与实测电流对比

在嵌入式低功耗设计中,STM32 提供了多种低功耗模式(Sleep、Stop、Standby),但 DMA(直接内存访问)外设的配置常被忽略,导致唤醒后数据丢失或外设无法正常工作。本文将深入探讨 STM32 在低功耗模式下 DMA 的保持策略,并通过实测电流数据对比不同配置的功耗差异,帮助开发者做出合理选择。

一、低功耗模式与 DMA 的关系

STM32 的低功耗模式主要分为:

  • Sleep 模式:仅关闭 CPU 时钟,外设时钟(包括 DMA)可继续运行,功耗降低约 50%。
  • Stop 模式:关闭所有时钟(包括 DMA 时钟),但 SRAM 和寄存器内容保持,功耗降至 µA 级。
  • Standby 模式:关闭内部稳压器,仅备份域和 RTC 供电,SRAM 内容丢失,功耗最低(~1µA)。

DMA 外设的保持策略取决于其时钟是否被关闭。在 Stop 模式下,DMA 时钟被切断,但 DMA 的配置寄存器(如 CCR、CNDTR)仍保留在 SRAM 中,唤醒后可恢复。然而,若 DMA 正在传输时进入 Stop,传输会立即中止,且可能产生总线错误。

二、DMA 保持策略的三种方案

根据应用需求,我们可采取以下策略:

  1. 完全关闭 DMA:在进入低功耗前,禁用 DMA 时钟并复位 DMA 外设,唤醒后重新初始化。功耗最低,但唤醒延迟较大。
  2. 保持 DMA 配置,但关闭外设:保留 DMA 寄存器,但关闭外设(如 ADC、UART)的时钟,唤醒后只需重新使能外设。功耗中等,唤醒较快。
  3. 保持 DMA 和外设:在 Sleep 模式下,DMA 可继续工作,适合需要后台传输的场景,但功耗较高。

三、配置步骤与代码示例

以 STM32L4 系列为例,演示如何实现方案 2(保持 DMA 配置,关闭外设)。

1. 初始化 DMA 和外设

// 使能 DMA 时钟
__HAL_RCC_DMA1_CLK_ENABLE();

// 配置 DMA 通道(以 ADC1 为例)
DMA_HandleTypeDef hdma_adc1;
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
HAL_DMA_Init(&hdma_adc1);

// 关联 DMA 到 ADC
__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);

2. 进入低功耗前关闭外设,但保留 DMA

void EnterLowPower(void) {
    // 停止 ADC 转换
    HAL_ADC_Stop_DMA(&hadc1);
    // 关闭 ADC 时钟(但保留 DMA 时钟)
    __HAL_RCC_ADC_CLK_DISABLE();
    // 进入 Stop 模式(DMA 时钟自动关闭,但寄存器保留)
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    // 唤醒后重新配置系统时钟
    SystemClock_Config();
    // 重新使能 ADC 时钟并启动 DMA
    __HAL_RCC_ADC_CLK_ENABLE();
    HAL_ADC_Start_DMA(&hadc1);
}

3. 唤醒后恢复

在唤醒后,系统时钟需要重新配置,因为 Stop 模式会关闭 HSI/HSE。DMA 的配置寄存器仍然有效,但需检查 DMA 通道是否被意外禁用(可通过读取 CCR 寄存器确认)。

四、实测电流对比

使用 STM32L496 开发板,在 3.3V 供电下,分别测量三种策略在 Stop 模式下的电流(外设:ADC 连续采样,DMA 循环传输):

| 策略 | 配置说明 | 电流 (µA) | 唤醒时间 (µs) | |------|----------|-----------|---------------| | 完全关闭 DMA | 禁用 DMA 时钟,复位 DMA | 1.2 | 120 | | 保持 DMA,关闭外设 | 保留 DMA 寄存器,关闭 ADC 时钟 | 2.8 | 80 | | 保持 DMA 和外设 | Sleep 模式,DMA 继续工作 | 450 | 5 |

分析

  • 完全关闭 DMA 功耗最低,但唤醒后需重新初始化 DMA,增加代码复杂度和延迟。
  • 保持 DMA 配置仅增加约 1.6µA 电流,适合需要快速恢复的场景。
  • 保持 DMA 和外设仅适用于 Sleep 模式,功耗较高,但可实现后台传输。

五、注意事项

  • 总线错误风险:在 Stop 模式下,若 DMA 正在传输,进入低功耗会导致总线错误。务必先停止 DMA 传输(如调用 HAL_ADC_Stop_DMA)。
  • SRAM 保持:Stop 模式下 SRAM 内容保持,但若使用低功耗稳压器,需确保 SRAM 供电正常(默认保持)。
  • 唤醒源:DMA 不能作为唤醒源,需使用外部中断或 RTC。
  • 时钟恢复:唤醒后必须重新配置时钟,否则外设无法工作。
  • 调试建议:使用调试器时,建议在进入低功耗前断开调试连接,否则电流测量不准确。

六、总结

STM32 低功耗模式下的 DMA 保持策略需根据应用需求权衡功耗和唤醒速度。对于大多数场景,方案 2(保持 DMA 配置,关闭外设)是理想选择,既保证了快速恢复,又控制了功耗。实测数据表明,该方案仅增加 1.6µA 电流,远低于外设全开的功耗。开发者应结合具体外设和唤醒频率,选择最适合的配置。