一.什么是低功耗
低功耗是在嵌入式微处理器系列的一个重要优势,特别适用于需要长时间运行且功耗敏感的应用场景。在很多应用场合中对电子设备的功耗非常苛刻,如某些传感器信息采集设备,仅仅靠小型的电池提供能源,要求工作长达数年之久,所以很有必要从控制功耗入手。
二.STM32电源系统结构
VDDA和VSSA必须分别连到VDD和VSS
三.低功耗模式介绍
1.stm32具有运行,睡眠,停止,等待四种工作模式,上电后默认是在运行模式。当内核不需要继续运行,就可以选择进入后面的三种低功耗模式降低功耗,这三种模式中,电源消耗不同、唤醒时间不同、唤醒源不同,用户需要根据应用需求,选择最佳的低功耗模式。三种低功耗的模式说明如下图
低功耗模式一览
2.睡眠模式(sleep mode)
在睡眠模式下,cpu停止工作,但所有的外设仍然运行,时钟继续运转。用于暂时关闭CPU但外设需要继续工作的场景。
模式特点:
对系统影响小,但节能效果最差。
在睡眠模式下,所有的I/O口都保持在它们运行模式时的状态
进入条件:
当系统控制寄存器中的SLEEPDEEF位被清除(通常为0),并且SLEEPONEXIT位根据需求设置时。
执行WFI 或WFE指令来进入
唤醒条件:
任意一个中断都可以将系统从睡眠模式唤醒。
如果执行WFE指令进入sleep模式,则一旦发生唤醒事件时,MCU将唤醒。
2.1停机模式(stop mode)
在停机模式下,CPU和核心外围设备的时钟会停止,但部分唤醒源(如外部中断和某些定时器)扔在运行。适用于需要长时间等待外部事件唤醒的应用,如等待用户输入或外部信号。STOP模式实现了非常低的功耗,同时保留了SPAM和寄存器的内容。
模式特点:
节能效果好,程序不会复位。
在停机模式下,所有的I/O口都保持它们在运行时的状态。
退出停止模式时,HSI RC振荡器被选为系统时钟。
进入条件:
需要将SLEEPDEEP位设置为1以进入深度睡眠模式,然后通过设置电源控制/状态寄存器(PWR_CSR) 中的PDDS位为0来选择进入Stop模式。
根据需求设置LPDS位(LPDS = 0:表示在深睡眠模式下,电压调节器保持开启状态;LPDS = 1:表示 在深睡眠模式下,电压调节器进入低功耗模式。)。
执行WFI(Wait For Interrupt)或WFE(Wait For Event)指令来进入。
在进入Stop模式之前,通常需要关闭不必要的外设时钟,并保存需要保留的状态信息。
唤醒条件:
STOP模式可以通过外部中断(如按键中断,串口接受中断)等唤醒。
rtc闹钟,usb唤醒,以太网唤醒等也可以作为唤醒源,但这些通常需要外部中断来触发。
2.2待机模式(standby mode)
在该模式下,CPU,外围设备和时钟都被关闭,只保留唤醒逻辑和备份寄存器,这适用于不需要保留RAM内容可以从复位状态恢复的设备,常见于需要极低且稀疏唤醒的应用,待机模式时STM32中功耗最低的模式之一。
模式特点:
节能效果最好,但程序会独卫,只有少数条件唤醒。
在待机模式下,大部分IO引脚处于高阻态,只有复位引脚、TAMPER引脚(如果配置为防侵入或校准输出)和WKUP引脚可用作唤醒源。
进入条件:
待机模式进入前,需要清除电源控制/状态寄存器中的WUF位,以确保没有未处理的唤醒标志。
将SLEEPDEEP位设置为1以进入深度睡眠模式,并设置PDDS位为1来选择进入待机模式。 执行WFI或WFE指令进入待机模式。
唤醒条件:
可以通过WKUP引脚的上升沿唤醒。
RTC闹钟也可以作为唤醒源
独立看门狗(IWDG)复位和NRST引脚上的外部复位也可以唤醒STM32,但这通常用于系统复位而非 低功耗唤醒。
四.低功耗小实验
实验目的:
1.按下按键2,进入低功耗模式(睡眠,停机,待机)
2.按下按键1,退出低功耗模式
3.正常模式下 led1闪烁,进入低功耗模式led2常亮,退出则熄灭、
实验步骤:
实验采用的时按键中断唤醒,配置为上升沿触发。按键1刚好是待机模式需要WKUP唤醒引脚
1.初始化按键1,并开启中断
void lpwr_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
gpio_initstruct.Pin = GPIO_PIN_0;
gpio_initstruct.Mode = GPIO_MODE_IT_RISING;
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOA, &gpio_initstruct);
HAL_NVIC_SetPriority(EXTI0_IRQn,2,2);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
2.初始化按键2
void key_init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef gpio_iniystruct;
gpio_iniystruct.Pin = GPIO_PIN_1;
gpio_iniystruct.Mode = GPIO_MODE_INPUT;
gpio_iniystruct.Pull = GPIO_PULLUP;
gpio_iniystruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&gpio_iniystruct);
}
//按键扫描
uint8_t key_scan(void)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)
{
delay_ms(10);
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)
{
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_SET);
return 2;
}
}
return 0;
}
3.编写睡眠模式代码(这里只需要调用一个函数)定时器不暂停好像也可以。
void lpwr_enter_sleep(void)
{
HAL_SuspendTick();//暂停定时器
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON,PWR_SLEEPENTRY_WFI);
}
4.编写停机模式代码,由于退出停机模式后,系统会自动使用 HSI为系统时钟,所以要重新设置时钟。
void lpwr_enter_stop(void)
{
HAL_SuspendTick();//暂停定时器
led2_on();
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON,PWR_STOPENTRY_WFI);
led2_off();
//唤醒重新配置时钟
stm32_clock_init(RCC_PLL_MUL9);
}
5.编写待机模式代码,
void lpwr_enter_standby(void)
{
//使能电源时钟(关闭电压调节器)
__HAL_RCC_PWR_CLK_ENABLE();
//使能wake up 的引脚唤醒功能
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
//清除唤醒标记,不然一直保持唤醒状态
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
//进入待机模式
HAL_PWR_EnterSTANDBYMode();
led2_on();
}
6.main函数调用这里只实验一个模式。
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
lpwr_init();
key_init();
uint8_t i = 0;
while(1)
{
if (key_scan() == 2) //检测按键2
{
//lpwr_enter_sleep(); //进入睡眠模式
lpwr_enter_stop(); //进入停机模式
//lpwr_enter_standby(); //进入待机模式
}
if((i % 20) == 0) led1_toggle();
i++;
delay_ms(10);
}
}
实验现象:
现象
开头的概念大部分都参考了许多大佬的,只是为了辅助学习而用。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_72442663/article/details/143132692
|