引言
在物联网、可穿戴设备等电池供电场景中,MCU 大部分时间处于低功耗模式,仅需周期性醒来执行任务。STM32F4 系列支持多种低功耗模式,其中 STOP 模式在保留 SRAM 和寄存器内容的同时,可将电流降至微安级,是兼顾功耗与唤醒速度的理想选择。然而,STOP 模式下高频时钟停止,传统定时器无法工作,多数开发者会立即想到 RTC。但 RTC 唤醒精度通常为秒级,且需配置外部 32.768kHz 晶振,对于毫秒级精确唤醒需求(如传感器采样间隔 10ms)显得力不从心。
幸运的是,STM32F4 内置了 LPTIM(Low-Power Timer),它可在 STOP 模式下依靠低速时钟(如 LSI 或 LSE)独立运行,支持最高 16 位计数,配合时钟预分频,可实现微秒到秒级的灵活定时,且唤醒延迟极低。本文将手把手教你如何配置 LPTIM,实现不依赖 RTC 的毫秒级精确唤醒。
LPTIM 工作原理
LPTIM 是一个专为低功耗场景设计的 16 位定时器,其核心特性包括:
- 时钟源灵活:可选择 LSI(约 32kHz)、LSE(32.768kHz)或外部时钟,在 STOP 模式下 LSI 和 LSE 仍可运行。
- 独立于内核:LPTIM 计数不依赖 CPU 时钟,唤醒后无需重新初始化。
- 多种触发模式:支持单次、连续计数,以及比较匹配、自动重载等。
- 超低功耗:自身功耗仅微安级,对整体功耗影响极小。
在 STOP 模式下,LPTIM 使用其时钟源持续计数,当计数值达到预设的自动重载值(ARR)时,产生比较匹配事件,该事件可直接触发唤醒信号,将 MCU 从 STOP 模式拉回运行模式。唤醒后,CPU 可立即读取 LPTIM 状态,确认唤醒源。
硬件与时钟配置
以 STM32F407 为例,我们选择 LSI 作为 LPTIM 时钟源,频率约为 32kHz(实际范围 17~47kHz,需校准)。为了获得精确的毫秒定时,我们使用预分频器将 LSI 分频至 1kHz(即 1ms 计数一次)。
关键寄存器:
-
RCC->APB1ENR:使能 LPTIM1 时钟(注意:在 STOP 模式下,APB 时钟停止,但 LPTIM 时钟由独立时钟源提供)。 -
RCC->CSR:使能 LSI 并等待就绪。 -
LPTIM->CFGR:配置时钟源、预分频因子。 -
LPTIM->ARR:设置自动重载值,决定唤醒周期。 -
LPTIM->CR:使能 LPTIM 并启动。
配置步骤
1. 使能 LSI 时钟
void LSI_Init(void) {
RCC->CSR |= RCC_CSR_LSION; // 使能 LSI
while ((RCC->CSR & RCC_CSR_LSIRDY) == 0); // 等待就绪
}
2. 配置 LPTIM 时钟源与预分频
void LPTIM_Config(uint16_t arr_value) {
// 使能 LPTIM1 时钟(在正常运行模式下,APB1 时钟必须开启)
RCC->APB1ENR |= RCC_APB1ENR_LPTIM1EN;
// 选择 LSI 作为时钟源,并设置预分频为 32(LSI/32 ≈ 1kHz)
LPTIM->CFGR = (LPTIM_CFGR_CKSEL_1) | (LPTIM_CFGR_PRESC_2); // CKSEL=1 (LSI), PRESC=2 (分频32)
// 设置自动重载值,例如 arr_value=10 则 10ms 唤醒
LPTIM->ARR = arr_value;
// 使能 LPTIM,并启动单次模式(也可用连续模式)
LPTIM->CR |= LPTIM_CR_ENABLE;
LPTIM->CR |= LPTIM_CR_SNGSTRT; // 单次启动,也可用 CONT 位连续运行
}
3. 进入 STOP 模式并等待唤醒
void EnterStopMode(void) {
// 设置唤醒源为 LPTIM 事件
PWR->CR |= PWR_CR_LPDS; // 低功耗深睡眠(STOP 模式)
PWR->CR |= PWR_CR_CWUF; // 清除唤醒标志
__DSB();
// 进入 STOP 模式(WFI 或 WFE)
__WFI();
// 唤醒后,立即关闭 LPTIM 或重新配置
LPTIM->CR &= ~LPTIM_CR_ENABLE; // 可选:禁用 LPTIM
}
4. 完整示例:周期性唤醒执行任务
#include "stm32f4xx.h"
void SystemClock_Config(void); // 标准时钟配置,略
int main(void) {
HAL_Init();
SystemClock_Config();
// 初始化 LSI 和 LPTIM
LSI_Init();
LPTIM_Config(10); // 10ms 唤醒周期
while (1) {
// 进入 STOP 模式,等待 LPTIM 唤醒
EnterStopMode();
// 唤醒后执行任务(例如读取传感器)
// 注意:唤醒后系统时钟可能仍为 HSI,需重新配置或直接使用
GPIO_ToggleBits(GPIOD, GPIO_Pin_12); // 示例:翻转 LED
}
}
注意事项
- 时钟精度:LSI 频率误差较大(±50%),若需高精度定时,建议使用 LSE 外部晶振(32.768kHz),但需额外硬件。也可在运行时校准 LSI。
- 唤醒延迟:从 LPTIM 匹配到 CPU 执行第一条指令,存在约 5~10 个 LSI 周期的延迟,对于 1kHz 时钟,约 5~10ms,需在应用层补偿。
- LPTIM 复位:在 STOP 模式下,LPTIM 寄存器内容保留,但唤醒后建议重新初始化以确保状态干净。
- 中断与标志:LPTIM 比较匹配可产生中断,但唤醒时无需中断,直接通过 WFI 唤醒即可。若需中断处理,需在 NVIC 中使能 LPTIM 全局中断。
- 功耗优化:在 STOP 模式下,关闭所有不必要的外设时钟,并将 GPIO 设置为模拟输入或下拉,以降低漏电流。
- 调试注意:使用调试器时,STOP 模式可能导致连接断开,建议在调试时禁用低功耗或使用串口打印。
总结
通过 LPTIM,STM32F4 在 STOP 模式下实现了毫秒级精确唤醒,且不依赖 RTC,大大简化了低功耗设计。本文提供了从原理到代码的完整指南,帮助开发者快速上手。实际项目中,可根据需求调整预分频和 ARR 值,实现从 1ms 到 65 秒的灵活定时。掌握这一技巧,你的嵌入式设备将兼具超低功耗与高实时性。