打印
[应用相关]

STM32低功耗模式

[复制链接]
412|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-10-25 13:19 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一.什么是低功耗
低功耗是在嵌入式微处理器系列的一个重要优势,特别适用于需要长时间运行且功耗敏感的应用场景。在很多应用场合中对电子设备的功耗非常苛刻,如某些传感器信息采集设备,仅仅靠小型的电池提供能源,要求工作长达数年之久,所以很有必要从控制功耗入手。

二.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

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2028

主题

15903

帖子

13

粉丝