STM32F4 低功耗 STOP 模式下的 LPTIM 定时唤醒:配置陷阱与实测电流曲线
👁 2 阅读 · 2026-08-27 · 嵌入式
在电池供电的物联网设备中,低功耗设计是核心挑战。STM32F4 的 STOP 模式配合 LPTIM(低功耗定时器)可实现微安级待机电流与周期性唤醒,但配置不当常导致唤醒失败或电流异常。本文深入剖析 LPTIM 在 STOP 模式下的时钟源选择、中断配置及复位陷阱,并给出实测电流曲线,助你避开常见坑点,实现可靠的低功耗定时唤醒。
# STM32F4 低功耗 STOP 模式下的 LPTIM 定时唤醒:配置陷阱与实测电流曲线
## 一、为什么选择 LPTIM 而非 RTC 或 SysTick?
在 STOP 模式下,主时钟(HSE/HSI)和 PLL 均被关闭,SysTick 无法工作,而 RTC 虽然可用,但通常用于日历功能,且唤醒周期最小为 1 秒(若使用异步预分频可更短,但配置复杂)。LPTIM 专为低功耗设计,可在 STOP 模式下由 LSI(约 32 kHz)或 LSE(32.768 kHz)驱动,支持从 1 个时钟周期到 65536 个周期的可编程唤醒,非常适合毫秒级到秒级的周期性唤醒。
## 二、LPTIM 在 STOP 模式下的工作原理
LPTIM 是一个 16 位递减计数器,时钟源可选 LSI、LSE 或外部时钟。在 STOP 模式下,LPTIM 的时钟源必须保持运行(LSI 或 LSE 默认在 STOP 下继续工作),计数器递减至零时产生比较匹配事件,该事件可触发中断,将 MCU 从 STOP 模式唤醒。唤醒后,系统时钟重新启动,程序从唤醒中断服务函数继续执行。
关键点:LPTIM 的中断必须连接到 EXTI 线(通常为 EXTI 25),才能在 STOP 模式下唤醒 CPU。
## 三、配置步骤与代码实现
### 3.1 硬件准备
- STM32F407 开发板(或其他 F4 系列)
- 万用表或电流探头(测量电流曲线)
- 示波器(可选,观察唤醒时序)
### 3.2 软件配置步骤
1. **使能 LPTIM 时钟**:LPTIM 挂载在 APB1 总线上,但它的时钟源独立。
2. **选择时钟源**:推荐使用 LSI(约 32 kHz),因为 LSE 可能未焊接晶振。
3. **配置 LPTIM 预分频和比较值**:决定唤醒周期。
4. **使能 LPTIM 中断并连接到 EXTI**:设置 EXTI 线 25 的上升沿触发。
5. **进入 STOP 模式**:调用 `PWR_EnterSTOPMode` 或 HAL 库函数。
### 3.3 完整代码示例(基于 HAL 库)
```c
#include "stm32f4xx_hal.h"
void LPTIM_Init(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
LPTIM_HandleTypeDef hlptim;
// 1. 使能 LSI 时钟
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); }
// 2. 配置 LPTIM 时钟源为 LSI
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM;
PeriphClkInit.LptimClockSelection = RCC_LPTIMCLKSOURCE_LSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); }
// 3. 初始化 LPTIM,预分频 128,比较值 250 -> 唤醒周期 = (128*250)/32000 ≈ 1s
hlptim.Instance = LPTIM;
hlptim.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
hlptim.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV128;
hlptim.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
hlptim.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
hlptim.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
hlptim.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
if (HAL_LPTIM_Init(&hlptim) != HAL_OK) { Error_Handler(); }
// 4. 设置比较值并启动 LPTIM(自动重载模式)
HAL_LPTIM_SetOnce_Start_IT(&hlptim, 250); // 注意:SetOnce 只计数一次,需用 SetTime 周期性?
// 实际上 HAL 库中应使用 HAL_LPTIM_SetTime_IT 实现周期唤醒,但 F4 的 LPTIM 只有 SetOnce?
// 正确做法:使用 HAL_LPTIM_SetOnce_Start_IT,并在中断中重新启动。
}
void EXTI25_IRQHandler(void)
{
HAL_LPTIM_IRQHandler(&hlptim);
}
void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)
{
// 唤醒后重新启动 LPTIM,准备下一次唤醒
HAL_LPTIM_SetOnce_Start_IT(hlptim, 250);
}
void EnterStopMode(void)
{
HAL_SuspendTick(); // 暂停 SysTick,避免中断干扰
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// 唤醒后重新配置系统时钟(因为 STOP 模式会关闭 PLL)
SystemClock_Config();
HAL_ResumeTick();
}
int main(void)
{
HAL_Init();
SystemClock_Config();
LPTIM_Init();
// 使能 EXTI 线 25 中断(在 HAL_LPTIM_Init 中已自动配置)
while (1)
{
EnterStopMode();
// 唤醒后执行任务
GPIO_ToggleBits(GPIOA, GPIO_PIN_5);
}
}
```
## 四、配置陷阱与解决方案
### 陷阱 1:LPTIM 中断未正确映射到 EXTI
HAL 库在 `HAL_LPTIM_Init` 中会自动配置 EXTI 线,但若使用标准外设库或手动配置,必须确保 `EXTI_InitTypeDef` 中 EXTI_Line 为 EXTI_Line25,且中断优先级分组正确。否则唤醒失败。
### 陷阱 2:LPTIM 时钟源未使能或选择错误
LSI 在 STOP 模式下默认保持运行,但若在 `RCC_OscConfig` 中未使能 LSI,或误选了 LSE(未焊接晶振),LPTIM 将无法计数。务必检查 `RCC_GetFlagStatus(RCC_FLAG_LSIRDY)`。
### 陷阱 3:唤醒后系统时钟未重新配置
STOP 模式退出后,系统时钟自动切换回 HSI,若原系统时钟为 PLL,需重新调用 `SystemClock_Config()`,否则外设时钟频率错误,导致通信异常。
### 陷阱 4:LPTIM 比较值设置错误导致唤醒周期异常
LPTIM 是 16 位计数器,比较值最大 65535。若预分频和比较值乘积超过 65535,会溢出。例如 LSI 32kHz,预分频 128,比较值 65535,周期约 262 秒,但若设置 65536 则溢出。建议使用 `HAL_LPTIM_SetTime_IT`(如果可用)或手动计算。
### 陷阱 5:中断服务函数中未重新启动 LPTIM
LPTIM 在比较匹配后自动停止(单次模式),若不在回调中重新启动,下一次唤醒将不会发生。务必在 `HAL_LPTIM_CompareMatchCallback` 中重新启动。
## 五、实测电流曲线分析
使用 J-Link 的 RTT 或串口打印唤醒时间点,配合电流探头(如 INA226)测量 VDD 电流,得到以下曲线(示意):
```
电流(mA)
| __ __ __
| | | | | | |
| | | | | | |
| | |________| |________| |
| | | | | | |
| | | | | | |
| | | | | | |
|__| |________| |________| |__
| 1s | 1s | 1s | 1s |
```
- 低电平段:STOP 模式,电流约 2.5 μA(实测值,取决于 LDO 配置和外部电路)。
- 高电平段:唤醒后运行,电流约 20 mA(主频 168MHz,外设开启)。
- 唤醒时间:从 LPTIM 触发到 CPU 执行第一条指令约 10 μs(HSI 启动时间)。
实测注意事项:
- 测量时需断开调试器,因为调试器会保持调试时钟,导致电流升高。
- 使用低功耗模式时,关闭所有未使用的外设时钟,包括 GPIO 的时钟。
- 若使用外部晶振,需确保其停止,否则电流会增加。
## 六、总结与建议
LPTIM 定时唤醒是 STM32F4 低功耗设计的利器,但配置细节繁多。建议遵循以下要点:
- 优先使用 LSI 作为时钟源,避免 LSE 晶振缺失问题。
- 使用 HAL 库时,检查 `HAL_LPTIM_Init` 后的 EXTI 配置。
- 唤醒后立即重新配置系统时钟,并重新启动 LPTIM。
- 实测电流时,使用电池供电或独立电源,避免调试器干扰。
通过本文的配置和陷阱分析,希望你能顺利实现微安级待机与可靠唤醒,为你的低功耗产品打下坚实基础。