# STM32F4 低功耗 STOP 模式下 DMA 传输的可行性分析与实测 ## 一、问题背景 在低功耗嵌入式设计中,STOP 模式是常用策略:内核停止、时钟关闭,功耗降至 µA 级。但若外设(如 ADC、UART)需要持续采集数据,DMA 能否在 STOP 模式下继续搬运?很多开发者想当然地认为“DMA 是硬件,应该可以”,但实测往往打脸。本文以 STM32F407 为例,从架构层面剖析,并给出实测数据。 ## 二、STOP 模式下的时钟与总线行为 ### 2.1 时钟树关键点 - STOP 模式下,**所有时钟(HSE、HSI、PLL)均被关闭**,仅 LSI 或 LSE 可继续运行(供 RTC、IWDG 使用)。 - **AHB1、AHB2、APB1、APB2 总线时钟全部停止**,这意味着挂载在总线上的外设(包括 DMA)的时钟源被切断。 - 但部分外设具有**独立时钟源**(如 RTC 使用 LSE,LPTIM 使用 LSI),它们不依赖系统时钟,可在 STOP 下运行。 ### 2.2 DMA 的依赖关系 - DMA 控制器本身挂载在 AHB1 总线上,其时钟由 `RCC->AHB1ENR` 控制。 - DMA 的传输需要**系统时钟(HCLK)** 驱动其状态机,以及**外设时钟**(如 ADC 时钟)产生触发事件。 - 在 STOP 模式下,HCLK 停止,DMA 的寄存器无法被访问,传输状态机冻结,**DMA 不可能继续传输**。 > 结论:**STM32F4 在 STOP 模式下,DMA 完全停止,无法保持传输。** 这与 STM32L4 系列不同(L4 的 DMA 支持 LP 模式,但仅限特定外设)。 ## 三、实测验证 ### 3.1 测试环境 - 硬件:STM32F407VET6 开发板,USART1 连接 USB-TTL,ADC1 采样内部温度传感器。 - 软件:HAL 库,Keil MDK 5.3。 - 目标:在 STOP 模式下,尝试用 DMA 搬运 ADC 数据,观察是否成功。 ### 3.2 代码设计 ```c // 初始化 ADC1 + DMA(正常模式) void ADC_DMA_Init(void) { __HAL_RCC_ADC1_CLK_ENABLE(); __HAL_RCC_DMA2_CLK_ENABLE(); // DMA2 Stream0 配置为 ADC1 通道 hdma.Init.Channel = DMA_CHANNEL_0; hdma.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma.Init.PeriphInc = DMA_PINC_DISABLE; hdma.Init.MemInc = DMA_MINC_ENABLE; hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma.Init.Mode = DMA_CIRCULAR; HAL_DMA_Init(&hdma); __HAL_LINKDMA(&hadc, DMA_Handle, hdma); // ADC 配置略... } // 进入 STOP 模式,并尝试继续 DMA void EnterStopMode_Test(void) { HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buffer, 10); HAL_Delay(10); // 确保 DMA 开始工作 // 进入 STOP 模式 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // 唤醒后(通过 EXTI 或 RTC 唤醒)检查数据 HAL_ADC_Stop_DMA(&hadc); // 打印 adc_buffer,观察是否有新数据 } ``` ### 3.3 实测结果 - 进入 STOP 后,用示波器测量 ADC 的 EOC 信号,发现**无任何脉冲**,说明 ADC 未工作。 - 唤醒后读取 `adc_buffer`,数据与进入 STOP 前完全一致,**无更新**。 - 功耗测量:STOP 模式下电流约 8µA(符合预期),但数据采集完全中断。 **结论:实测证实,STOP 模式下 DMA 传输不可行。** ## 四、替代方案:如何在低功耗下保持数据采集 ### 4.1 方案一:使用 LPTIM + LPUART(仅限特定型号) - STM32F4 系列**没有 LPUART**(L0/L4 系列才有),但部分 F4 型号(如 F410)有 LPTIM。 - LPTIM 可使用 LSI 时钟,在 STOP 模式下运行,并产生事件唤醒 MCU,但**不能直接驱动 DMA**。 - 可行做法:LPTIM 定时唤醒 MCU,在短暂运行模式下用 DMA 采集数据,然后再次进入 STOP。 ### 4.2 方案二:RTC 周期性唤醒 + 快速采集 - RTC 使用 LSE,可在 STOP 下运行,产生闹钟事件唤醒 MCU。 - 唤醒后,在短时间内完成 DMA 传输(如 ADC 采样),然后重新进入 STOP。 - 优点:功耗低(唤醒时间短),数据不丢失;缺点:实时性差,适合低频采集。 ### 4.3 方案三:使用外部 ADC + SPI(主从模式) - 外部 ADC 由独立电源供电,通过 SPI 接口与 MCU 通信。 - MCU 在 STOP 模式下,SPI 不工作,但外部 ADC 可自行采集并存储(需自带 FIFO)。 - MCU 唤醒后一次性读取,适合高速采样场景。 ## 五、注意事项 - **不要试图在 STOP 模式下访问任何外设寄存器**,包括 DMA,否则会触发总线错误或死机。 - 进入 STOP 前,务必关闭 DMA 并等待传输完成,否则可能丢失数据。 - 唤醒后,需重新初始化外设时钟(HAL 库会自动处理),但 DMA 配置可能需要重新设置。 - 使用 `HAL_PWR_EnterSTOPMode` 时,注意选择稳压器模式(`PWR_LOWPOWERREGULATOR_ON` 比 `PWR_MAINREGULATOR_ON` 功耗更低,但唤醒时间更长)。 - 若必须连续采集,考虑使用 **STOP2 模式(仅限 L4 系列)** 或 **SLEEP 模式**(功耗略高,但 DMA 可用)。 ## 六、总结 STM32F4 的 STOP 模式设计目标是极致省电,因此牺牲了大部分外设功能。DMA 依赖系统时钟,在 STOP 下必然停止。开发者应根据应用需求,选择合适的低功耗策略:要么接受中断式采集,要么升级到支持 LP 模式的系列(如 STM32L4)。实测数据表明,任何绕过 STOP 限制的尝试都是徒劳的,但通过合理设计唤醒机制,仍可满足低功耗与数据采集的平衡。