# 引言 在物联网、可穿戴设备等电池供电场景中,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 时钟 ```c void LSI_Init(void) { RCC->CSR |= RCC_CSR_LSION; // 使能 LSI while ((RCC->CSR & RCC_CSR_LSIRDY) == 0); // 等待就绪 } ``` ## 2. 配置 LPTIM 时钟源与预分频 ```c 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 模式并等待唤醒 ```c 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. 完整示例:周期性唤醒执行任务 ```c #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 秒的灵活定时。掌握这一技巧,你的嵌入式设备将兼具超低功耗与高实时性。