STM32F4 低功耗 STOP 模式下的 RTC 与 DMA 数据采集完整配置方案
👁 4 阅读 · 2026-08-27 · 嵌入式
在电池供电的物联网设备中,低功耗与数据采集的平衡至关重要。STM32F4 系列支持 STOP 模式,可将功耗降至微安级,但如何在此模式下保持 RTC 运行并利用 DMA 连续采集数据,是许多开发者面临的挑战。本文深入剖析 STOP 模式的工作原理,详细讲解 RTC 唤醒与 DMA 传输的配置步骤,并提供完整代码示例,帮助你在低功耗场景下实现可靠的数据记录。
# 引言
在嵌入式系统设计中,低功耗与数据完整性往往相互制约。STM32F4 系列凭借其丰富的外设和灵活的电源管理,成为许多便携式设备的首选。STOP 模式是 STM32F4 低功耗策略中的关键一环,它关闭大部分时钟,但保留 SRAM 和寄存器内容,功耗可低至 10µA 左右。然而,要在 STOP 模式下保持 RTC 计时并让 DMA 持续采集传感器数据,需要精心的时钟配置和外设协作。本文将带你一步步实现这一方案。
# 1. 原理剖析:STOP 模式下的外设行为
## 1.1 STOP 模式概述
STOP 模式基于 Cortex-M4 内核的 SLEEPDEEP 机制。进入 STOP 后,所有时钟(包括 HSE、HSI、PLL)均被关闭,但以下模块保持供电:
- **SRAM 和寄存器**:内容不丢失。
- **RTC**:若使用 LSI 或 LSE 作为时钟源,可继续运行。
- **备份域**:包括备份寄存器、RTC 等。
- **部分 GPIO**:可配置为唤醒源。
关键点:DMA 在 STOP 模式下默认停止,因为其时钟(AHB/APB)被关闭。但我们可以通过**外部事件**或**RTC 唤醒**来短暂唤醒系统,执行 DMA 传输,再重新进入 STOP,实现“间歇性采集”。
## 1.2 RTC 与 DMA 的协作策略
- **RTC 唤醒**:配置 RTC 闹钟或唤醒定时器,周期性产生唤醒事件(如每 1 秒)。
- **DMA 采集**:唤醒后,系统时钟恢复,DMA 可快速将 ADC 或传感器数据搬运到内存,然后再次进入 STOP。
- **数据缓存**:使用双缓冲或环形缓冲区,避免数据覆盖。
# 2. 硬件准备
- 开发板:STM32F407 Discovery 或类似板卡
- 传感器:如 MPU6050(I2C 接口)或内部 ADC 采样
- 工具:STM32CubeIDE 或 Keil MDK
# 3. 配置步骤
## 3.1 时钟配置
1. **使能 LSE 或 LSI**:RTC 需要独立时钟源。推荐使用 LSE(32.768kHz),精度更高。
```c
RCC_BackupResetCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_ON);
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
```
2. **配置系统时钟**:正常运行时使用 HSE+PLL,进入 STOP 前无需切换,因为 STOP 会关闭它们。
## 3.2 RTC 配置
1. **使能 PWR 时钟**:访问电源控制寄存器。
```c
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
```
2. **配置 RTC 唤醒定时器**:
```c
RTC_WakeUpCmd(DISABLE);
RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits); // 1Hz 计数
RTC_SetWakeUpCounter(1); // 1 秒唤醒
RTC_WakeUpCmd(ENABLE);
RTC_ITConfig(RTC_IT_WUT, ENABLE);
```
3. **使能 RTC 中断**:在 NVIC 中配置。
## 3.3 DMA 配置(以 ADC 为例)
1. **初始化 ADC**:配置为连续转换或外部触发。
2. **配置 DMA**:将 ADC 数据寄存器映射到内存缓冲区。
```c
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_DeInit(DMA2_Stream0);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)adc_buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream0, ENABLE);
```
## 3.4 进入 STOP 模式
在进入 STOP 前,确保 DMA 已停止(或暂停),然后执行:
```c
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
```
注意:进入 STOP 后,DMA 时钟关闭,传输会暂停。唤醒后需重新使能。
## 3.5 唤醒处理
在 RTC 唤醒中断中:
1. 清除中断标志。
2. 重新配置系统时钟(如果使用 HSE/PLL,需重新初始化)。
3. 重新使能 DMA 并启动传输。
4. 处理数据(如存储到 Flash 或发送)。
5. 再次进入 STOP。
# 4. 完整代码示例
以下代码演示了核心逻辑(基于标准外设库):
```c
// 全局变量
uint16_t adc_buffer[128];
volatile uint8_t wakeup_flag = 0;
void RTC_WKUP_IRQHandler(void) {
if (RTC_GetITStatus(RTC_IT_WUT) != RESET) {
RTC_ClearITPendingBit(RTC_IT_WUT);
wakeup_flag = 1;
}
}
void SystemClock_Config(void) {
// 配置 HSE、PLL,使能 FLASH 预取等(略)
}
void ADC_DMA_Config(void) {
// 初始化 ADC1 和 DMA2_Stream0(见上文)
}
void Enter_StopMode(void) {
// 停止 DMA 传输
DMA_Cmd(DMA2_Stream0, DISABLE);
// 进入 STOP 模式
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
// 唤醒后重新配置系统时钟
SystemClock_Config();
// 重新使能 DMA
DMA_Cmd(DMA2_Stream0, ENABLE);
}
int main(void) {
// 初始化时钟、RTC、ADC、DMA、NVIC
SystemClock_Config();
RTC_Config();
ADC_DMA_Config();
NVIC_Config();
while (1) {
Enter_StopMode();
if (wakeup_flag) {
wakeup_flag = 0;
// 处理采集到的数据(此时 DMA 已重新使能,但需等待传输完成)
// 例如:存储到外部 Flash 或通过 UART 发送
}
}
}
```
# 5. 注意事项
- **时钟恢复**:从 STOP 唤醒后,系统时钟默认使用 HSI,若需高性能,必须重新配置 PLL。
- **DMA 缓冲管理**:使用双缓冲时,注意切换时机,避免数据覆盖。
- **RTC 时钟源**:LSE 在低功耗下更稳定,但 LSI 无需外部晶振,适合成本敏感设计。
- **唤醒源**:除了 RTC,还可配置 EXTI 外部引脚唤醒,但需注意 GPIO 状态。
- **调试**:在 STOP 模式下,SWD 调试可能失效,建议使用串口打印调试信息。
- **功耗测量**:实际功耗受 GPIO 漏电流影响,未使用的引脚应配置为模拟输入或下拉。
# 6. 总结
通过合理配置 RTC 唤醒和 DMA 传输,STM32F4 可以在 STOP 模式下实现低功耗与数据采集的平衡。本文提供的方案适用于周期性数据记录场景,如环境监测、可穿戴设备等。开发者可根据实际需求调整唤醒周期和采样率,进一步优化功耗。记住,低功耗设计是一个系统工程,需从硬件到软件全面考虑。