文章目录
一、低功耗模式
STM32 微控制器提供了多种低功耗模式,帮助开发者在需要时降低系统功耗,特别适用于电池供电或节能要求的应用场景。主要低功耗模式有三个:睡眠模式、停止模式、待机模式。
1.1.睡眠模式
特点:仅CPU停止工作,外设继续运行;任何中断或事件都可唤醒。
唤醒时间:最短,无时钟重启延迟。
功耗:中等
1.2.停止模式
特点:CPU和大部分时钟停止;保留SRAM和寄存器内容;可用外部中断、RTC闹钟等唤醒。
唤醒时间:中等,需要时钟重启。
功耗:较低
1.3.待机模式
特点:几乎关闭所有电路;仅保留备份域(如有RTC);可用WKUP引脚、RTC闹钟等唤醒。
唤醒时间:最长,相当于复位重启。
功耗:最低
二、Tickless低功耗模式
2.1.简介
Tickless(无系统节拍) 是一种用于实时操作系统(RTOS,如FreeRTOS、RT-Thread等)的低功耗技术,它通过动态调整 SysTick 来减少不必要的 CPU 唤醒,从而降低功耗。Tickless 模式:当系统进入空闲状态时,RTOS 会计算下一个任务的最早唤醒时间,并暂时关闭 SysTick,让 CPU 进入低功耗状态(如睡眠模式)。在任务就绪前,再通过低功耗定时器(如RTC 或 LPTIM)唤醒 CPU。其实 Tickless 低功耗模式的本质是通过调用指令 WFI 实现睡眠模式。
2.2.详解
下面表格是基本低功耗模式和 Tickless 对比:
特性 | 低功耗模式 | Tickless 模式 |
---|---|---|
本质 | STM32 硬件提供的多种省电状态 | FreeRTOS 等 RTOS 的节能调度策略 |
层级 | 硬件层面 | 操作系统 / 软件层面 |
目的 | 通过关闭 / 降频硬件模块降低功耗 | 通过动态调整系统节拍减少不必要的中断 |
在任务运行时间统计实验中可以看出来,在整个系统运行过程中,其实大部分时间都是在执行空闲任务(是在系统中的所有其他任务都阻塞或被挂起时才运行的),如下图所示:
为了降低功耗,又不影响系统运行,可以在本该空闲任务执行期间,让 MCU 进入相应的低功耗模式;当其他任务准备运行的时候,唤醒 MCU 退出低功耗模式,但是进入低功耗之后,多久唤醒,下一个要运行的任务如何被准确唤醒?任何中断均可唤醒 MCU,若滴答定时器频繁中断则会影响低功耗的效果。这些问题可以这样解决:
- 将滴答定时器的中断周期修改为低功耗运行时间
- 推出低功耗之后,补上系统时钟节拍数
三、Tickless模式相关配置项
- 使能低功耗 Tickless 模式:
configUSE_TICKLESS_IDLE
- 定义系统进入相应低功耗模式的最短时长:
configEXPECTED_IDLE_TIME_BEFORE_SLEEP
- 定义需要在系统进入低功耗模式之前执行的事务,例如:进入低功耗之前关闭外设时钟,以降低功耗:
configPRE_SLEEP_PROCESSING(x)
,需要自己在 FreeRTOSconfig.h 里面自己定义 - 定义需要在系统退出低功耗模式之后执行的事务,例如:退出低功耗之后开启被关闭的外设时钟,使系统能够正常运行:
configPOST_SLEEP_PROCESSING(x)
,需要自己在 FreeRTOSconfig.h 里面自己定义
四、实验
4.1.实验设计
在二值信号量的代码上,加入低功耗模式,最后对比这两个实验的功耗结果
4.2.软件设计
在 FreeRTOSconfig.h 里面的configUSE_TICKLESS_IDLE
宏配置成 1:
#define configUSE_TICKLESS_IDLE 1
定义系统进入相应低功耗模式的最短时长的宏默认配置为 2:
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2
接着在 FreeRTOSconfig.h 文件中找个位置定义下面函数:
#include "freertos_demo.h"
#define configPRE_SLEEP_PROCESSING( x ) PRE_SLEEP_PROCESSING()
#define configPOST_SLEEP_PROCESSING( x ) POSR_SLEEP_PROCESSING()
并在 freertos_demo.h 文件里声明这两个函数:
void PRE_SLEEP_PROCESSING(void);
void POST_SLEEP_PROCESSING(void);
在 freertos_demo.c 文件里,入口函数上面定义下面两个函数:
//进入低功耗模式前要关闭的事情
void PRE_SLEEP_PROCESSING(void)
{
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOD_CLK_DISABLE();
__HAL_RCC_GPIOE_CLK_DISABLE();
__HAL_RCC_GPIOF_CLK_DISABLE();
__HAL_RCC_GPIOG_CLK_DISABLE();
}
//退出低功耗模式后需要打开的事情
void POST_SLEEP_PROCESSING(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
}
下图未使用低功耗模式,功耗为 1.059W:
下图使用低功耗模式,功耗为 0.980W