)
目录一STM32低功耗模式11.2V 域 vs VDD 域 vs 调压器2三种低功耗模式本质3一张图解释停机和待机4正点例程采用睡眠模式二实验分析1正点实验内容2用到的几个宏三实验改动rtos\22\ 改动清单freertos_demo.cFreeRTOSConfig.hmain.c钩子函数运行逻辑总结一STM32低功耗模式模式名称进入唤醒对 1.2V 域时钟的影响对 VDD 域时钟的影响调压器睡眠(立即休眠或退出是休眠)WFI任意中断CPU CLK 关闭对其它时钟或模拟时钟源无影响无开启WFE唤醒事件停止PDDS 和 LPDS 位 SLEEPDEEP 位WFI 或 WFE任意 EXTI 线(在 EXTI 寄存器中配置内部线和外部线)所有 1.2 V 域时钟都关闭HSI 和 HSE 振荡器关闭开启或处于低功耗模式待机PDDS 位 SLEEPDEEP 位WFI 或 WFEWKUP 引脚上升沿、RTC 闹钟(闹钟 A 或闹钟 B)、RTC 唤醒事件、RTC 入侵事件、RTC 时间戳事件、NRST 引脚外部复位、IWDG 复位所有 1.2 V 域时钟都关闭HSI 和 HSE 振荡器关闭关闭11.2V 域 vs VDD 域 vs 调压器芯片供电秘密F429 外接 3.3VVDD但 Cortex-M4 核心实际跑在1.2V。芯片内部有个调压器把 3.3V → 1.2V外部 3.3V (VDD) │ ├──────────────────────────→ 直接给 GPIO、USART、SPI、RTC 备份域 │ ↑ 这部分就是 VDD 域 │ └──→ 调压器 → 1.2V ──→ CPU、NVIC、SRAM、Flash、DMA、大部分外设 ↑ 这部分就是 1.2V 域2三种低功耗模式本质睡眠停止待机CPU 钟关关关1.2V 域外设、SRAM开着全关全关VDD 域GPIO、RTC开着开着开着调压器开着开着/半开关唤醒后原地继续程序从头跑但 SRAM 还在程序从头跑SRAM 全丢3一张图解释停机和待机睡眠模式CPU 打盹店还开着 拉下卷帘门WFI→ CPU 不干活了 但店里的灯外设时钟、收银机SRAM全开着 有人敲门任意中断→ 门一拉就起来 → 瞬间恢复 停止模式打烊但不锁门 灯关了1.2V 域时钟全关包括外设、CPU 收银机还通着电调压器还在SRAM 保持 只有应急灯亮着VDD 域——GPIO 能检测电平变化 外部中断、RTC 闹钟 → 重新开灯 → 程序接着跑 待机模式彻底断电只留一把钥匙 整店断电调压器关了 → 1.2V 域没了 → SRAM 全丢 唯一的唤醒方式WKUP 引脚、RTC 闹钟、复位 醒了 重新开店程序从 main 重新开始跟复位一样低功耗 Tickless 就是用停止/待机模式FreeRTOS 没有任务要跑的时候不跑 SysTick 空转直接把芯片塞进低功耗模式RTC 闹钟到了再叫醒。4正点例程采用睡眠模式睡眠模式CPU 停了但外设和 SysTick 还活着——一个定时器中断立马能叫醒程序原地继续什么状态都不丢。实验做起来简单改个配置就行。停止/待机模式醒了程序要从头跑或者重新初始化所有外设——FreeRTOS 状态全丢恢复起来复杂度高一截。教学中一般不碰这两个。正点的 Tickless 实验就是开了configUSE_TICKLESS_IDLEIdle 任务在没有 Run 的时候不空转 SysTick而是调WFI让 CPU 睡觉。SysTick 到点或者外部中断来了自动醒。代码很简单——改几个宏配一个恢复函数。二实验分析1正点实验内容代码完全复用二值信号量实验只是多开了configUSE_TICKLESS_IDLE 1和两个钩子// 进 WFI 前关掉不用 GPIO 的时钟省电 void PRE_SLEEP_PROCESSING(void) { __HAL_RCC_GPIOA_CLK_DISABLE(); // 全关 __HAL_RCC_GPIOB_CLK_DISABLE(); ... } // WFI 醒来重新打开 void POST_SLEEP_PROCESSING(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); // 全开 ... }运行时流程task1 扫键10ms 醒一次 task2 死等信号量永远睡着 没有任务要跑时 → Idle 跑 → 算下次谁要醒 → WFI 睡觉 → 省电 ↓ 到点了或中断来了 POST_SLEEP_PROCESSING → 恢复 GPIO 时钟 → 调度器继续跑2用到的几个宏宏作用不改行不行configUSE_TICKLESS_IDLE 1总开关必须改configEXPECTED_IDLE_TIME_BEFORE_SLEEP空闲时间 这个值就不进 WFI防止刚睡就被叫醒进出开销比省的电还大✅ 默认 2 tick不改也行configPRE_SLEEP_PROCESSING进 WFI 前要执行的操作✅ 默认空我们没在宏里写直接用弱函数PRE_SLEEP_PROCESSING()替代了configPOST_SLEEP_PROCESSING出 WFI 后要执行的操作✅ 同上正点 PPT 把四个宏全介绍了是讲原理——告诉你 Tickless 有这些可配置的点。实际动手时configUSE_TICKLESS_IDLE 1一开另外三个要么有默认值、要么我们已经用弱函数实现了不需要额外改。三实验改动rtos\22\ 改动清单freertos_demo.c行号内容54-82PRE_SLEEP_PROCESSINGPOST_SLEEP_PROCESSING— 睡前关 7 个 GPIO 时钟醒后开回来102-137二值信号量 两个任务复用 rtos\11\ 逻辑FreeRTOSConfig.h行号内容46configUSE_TICKLESS_IDLE0→1main.c行号内容26printf 标题 →FreeRTOS Tickless Test!Tickless 没有用户 API——只改一个宏 两个钩子业务代码完全不变。可以编译烧录了。钩子函数void PRE_SLEEP_PROCESSING(void) // 钩子1睡前被 FreeRTOS 调用 → 关 GPIO 时钟 { __HAL_RCC_GPIOA_CLK_DISABLE(); ... } void POST_SLEEP_PROCESSING(void) // 钩子2醒后被 FreeRTOS 调用 → 开回 GPIO 时钟 { __HAL_RCC_GPIOA_CLK_ENABLE(); ... }钩子 FreeRTOS 在 Idle 任务里 WFI 的前后给你留的空位。你不写这两个函数 → WFI 照常工作但 GPIO 时钟还开着 → 省电效果打折扣。你写了 → 睡前关掉、醒后开回 → 省更多电。运行逻辑总结正常运行时 task1每 10ms 醒一次扫按键 task2死等信号量阻塞 没有任务跑的时候 CPU 不是傻等 SysTick → 是进 Idle 任务 → 调 PRE_SLEEP → WFI 睡觉 → 等中断叫醒你什么键都不按的时候系统大部分时间在 WFI 里睡觉电流比普通 RTOS 低很多。正点的实验逻辑就是这么简单——用之前的二值信号量实验直接套上 Tickless 的开关。实验现象就是原例程输出给你对比的二值信号量创建成功 信号量释放成功 获取信号量成功 ← 按 KEY0 触发一次 信号量释放成功 获取信号量成功 ← 按 KEY1 触发一次功能一模一样只是不按键的时候 CPU 在睡觉省电。