# 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 和外设 ```c // 使能 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 ```c 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 电流,远低于外设全开的功耗。开发者应结合具体外设和唤醒频率,选择最适合的配置。