一.什么是低功耗

低功耗是在嵌入式微处理器系列的一个重要优势,特别适用于需要长时间运行且功耗敏感的应用场景。在很多应用场合中对电子设备的功耗非常苛刻,如某些传感器信息采集设备,仅仅靠小型的电池提供能源,要求工作长达数年之久,所以很有必要从控制功耗入手。

二.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);
        }
    }
    

    实验现象:

    现象

    开头的概念大部分都参考了许多大佬的,只是为了辅助学习而用。

    作者:走下去-别回头

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32低功耗模式

    发表回复