加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

STM32F10x進(jìn)入低功耗模式

04/02 07:04
3035
閱讀需 31 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

1 低功耗模式簡(jiǎn)介

在系統(tǒng)或電源復(fù)位以后,微控制器處于運(yùn)行狀態(tài)。當(dāng)CPU不需繼續(xù)運(yùn)行時(shí),可以利用多種低功耗模式來(lái)節(jié)省功耗,例如等待某個(gè)外部事件時(shí)。用戶需要根據(jù)最低電源消耗、最快速啟動(dòng)時(shí)間和可用的喚醒源等條件,選定一個(gè)最佳的低功耗模式。

STM32F10x有三種低功耗模式:

1、睡眠模式

Cortex-M3內(nèi)核停止,所有外設(shè)包括Cortex?-M3核心的外設(shè),如NVIC、系統(tǒng)時(shí)鐘(SysTick)等仍在運(yùn)行

2、停止模式

所有的時(shí)鐘都已停止

3、待機(jī)模式

1.8V電源關(guān)閉(CPU核心區(qū)域)

低功耗模式一覽:

在這里插入圖片描述

STM32電源框圖:
在這里插入圖片描述

此外,在運(yùn)行模式下,可以通過(guò)以下方式中的一種降低功耗:

1、降低系統(tǒng)時(shí)鐘。
2、關(guān)閉APB和AHB總線上未被使用的外設(shè)時(shí)鐘。

2 睡眠模式詳解

通過(guò)執(zhí)行WFI或WFE指令可以進(jìn)入睡眠狀態(tài)。根據(jù)Cortex?-M3系統(tǒng)控制寄存器中的SLEEPONEXIT位的值,有兩種選項(xiàng)可用于選擇睡眠模式進(jìn)入機(jī)制:

1、SLEEP-NOW:如果SLEEPONEXIT位被清除,當(dāng)WFI或WFE被執(zhí)行時(shí),微控制器立即進(jìn)入睡眠模式。
2、SLEEP-ON_EXIT:如果SLEEPONEXIT位被置位,系統(tǒng)從最低優(yōu)先級(jí)的中斷處理程序中退出時(shí),微控制器就立即進(jìn)入睡眠模式。

SLEEP-NOW模式一覽:

在這里插入圖片描述
SLEEP-ON_EXIT模式一覽:
在這里插入圖片描述

3 停止模式詳解

停止模式是在Cortex?-M3的深睡眠模式基礎(chǔ)上結(jié)合了外設(shè)的時(shí)鐘控制機(jī)制,在停止模式下電壓調(diào)節(jié)器可運(yùn)行在正?;虻凸哪J?。

此時(shí)在1.8V供電區(qū)域的的所有時(shí)鐘都被停止,PLL、HSI和HSE RC振蕩器的功能被禁止,SRAM和寄存器內(nèi)容被保留下來(lái)。

在停止模式下,所有的I/O引腳都保持它們?cè)谶\(yùn)行模式時(shí)的狀態(tài)。

停止模式進(jìn)入和退出的方法如下:

在這里插入圖片描述

進(jìn)入停止模式:

在停止模式下,通過(guò)設(shè)置電源控制寄存器(PWR_CR)的LPDS位使內(nèi)部調(diào)節(jié)器進(jìn)入低功耗模式,能夠降低更多的功耗。

需要注意:

1、如果正在進(jìn)行閃存編程,直到對(duì)內(nèi)存訪問(wèn)完成,系統(tǒng)才進(jìn)入停止模式。
2、如果正在進(jìn)行對(duì)APB的訪問(wèn),直到對(duì)APB訪問(wèn)完成,系統(tǒng)才進(jìn)入停止模式。
3、在進(jìn)入停止模式前,如果一些外設(shè)沒(méi)有被關(guān)閉,那么外設(shè)仍然消耗電流,如串口、ADC、DAC等。

退出停止模式:

通過(guò)中斷或者喚醒事件可以退出停止模式。

需要注意:

1、退出停止模式后,HSI RC振蕩器被默認(rèn)選為系統(tǒng)時(shí)鐘。
2、當(dāng)電壓調(diào)節(jié)器處于低功耗模式下,當(dāng)系統(tǒng)從停止模式退出時(shí),將會(huì)有一段額外的啟動(dòng)延時(shí)。如果在停止模式期間保持內(nèi)部調(diào)節(jié)器開(kāi)啟,則退出啟動(dòng)時(shí)間會(huì)縮短,但相應(yīng)的功耗會(huì)增加。

4 待機(jī)模式詳解

待機(jī)模式可實(shí)現(xiàn)系統(tǒng)的最低功耗。該模式是在Cortex-M3深睡眠模式時(shí)關(guān)閉電壓調(diào)節(jié)器。整個(gè)1.8V供電區(qū)域被斷電。PLL、HSI和HSE振蕩器也被斷電。SRAM和寄存器內(nèi)容丟失。只有備份的寄存器和待機(jī)電路維持供電。

待機(jī)模式進(jìn)入和退出的方法如下:

在這里插入圖片描述

進(jìn)入待機(jī)模式:

進(jìn)入待機(jī)模式需要做到以下幾點(diǎn):

1、設(shè)置Cortex-M3系統(tǒng)控制寄存器中的SLEEPDEEP位。
2、清除電源控制寄存器(PWR_CR)中的PDDS位。
3、通過(guò)設(shè)置PWR_CR中LPDS位選擇電壓調(diào)節(jié)器的模式。

退出待機(jī)模式:

當(dāng)一個(gè)外部復(fù)位(NRST引腳)、IWDG復(fù)位、WKUP引腳上的上升沿或RTC鬧鐘事件的上升沿發(fā)生時(shí),微控制器從待機(jī)模式退出。從待機(jī)喚醒后,除了電源控制/狀態(tài)寄存器(PWR_CSR),所有寄存器被復(fù)位。

從待機(jī)模式喚醒后的代碼執(zhí)行等同于復(fù)位后的執(zhí)行(采樣啟動(dòng)模式引腳、讀取復(fù)位向量等)。電源控制/狀態(tài)寄存器(PWR_CSR)將會(huì)指示內(nèi)核由待機(jī)狀態(tài)退出。

5 示例代碼

5.1 標(biāo)準(zhǔn)庫(kù)函數(shù)定義

睡眠模式標(biāo)準(zhǔn)庫(kù)函數(shù)代碼:

static __INLINE  void __WFI()                     { __ASM ("wfi"); }
static __INLINE  void __WFE()                     { __ASM ("wfe"); }

/**
  * @brief  Selects the condition for the system to enter low power mode.
  * @param  LowPowerMode: Specifies the new mode for the system to enter low power mode.
  *   This parameter can be one of the following values:
  *     @arg NVIC_LP_SEVONPEND
  *     @arg NVIC_LP_SLEEPDEEP
  *     @arg NVIC_LP_SLEEPONEXIT
  * @param  NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_NVIC_LP(LowPowerMode));
  assert_param(IS_FUNCTIONAL_STATE(NewState));  
  
  if (NewState != DISABLE)
  {
    SCB->SCR |= LowPowerMode;
  }
  else
  {
    SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode);
  }
}

停機(jī)模式標(biāo)準(zhǔn)庫(kù)函數(shù)代碼:

/**
  * @brief  Enters STOP mode.
  * @param  PWR_Regulator: specifies the regulator state in STOP mode.
  *   This parameter can be one of the following values:
  *     @arg PWR_Regulator_ON: STOP mode with regulator ON
  *     @arg PWR_Regulator_LowPower: STOP mode with regulator in low power mode
  * @param  PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction.
  *   This parameter can be one of the following values:
  *     @arg PWR_STOPEntry_WFI: enter STOP mode with WFI instruction
  *     @arg PWR_STOPEntry_WFE: enter STOP mode with WFE instruction
  * @retval None
  */
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
  uint32_t tmpreg = 0;
  /* Check the parameters */
  assert_param(IS_PWR_REGULATOR(PWR_Regulator));
  assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
  
  /* Select the regulator state in STOP mode ---------------------------------*/
  tmpreg = PWR->CR;
  /* Clear PDDS and LPDS bits */
  tmpreg &= CR_DS_MASK;
  /* Set LPDS bit according to PWR_Regulator value */
  tmpreg |= PWR_Regulator;
  /* Store the new value */
  PWR->CR = tmpreg;
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SCB->SCR |= SCB_SCR_SLEEPDEEP;
  
  /* Select STOP mode entry --------------------------------------------------*/
  if(PWR_STOPEntry == PWR_STOPEntry_WFI)
  {   
    /* Request Wait For Interrupt */
    __WFI();
  }
  else
  {
    /* Request Wait For Event */
    __WFE();
  }
  
  /* Reset SLEEPDEEP bit of Cortex System Control Register */
  SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);  
}

待機(jī)模式標(biāo)準(zhǔn)庫(kù)函數(shù)代碼:

/**
  * @brief  Enters STANDBY mode.
  * @param  None
  * @retval None
  */
void PWR_EnterSTANDBYMode(void)
{
  /* Clear Wake-up flag */
  PWR->CR |= PWR_CR_CWUF;
  /* Select STANDBY mode */
  PWR->CR |= PWR_CR_PDDS;
  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM   )
  __force_stores();
#endif
  /* Request Wait For Interrupt */
  __WFI();
}

5.2 進(jìn)入低功耗模式參考代碼

低功耗模式參考代碼:

#include "delay.h"
#include "sys.h"
#include "usart.h"

#define KEY0    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)  //讀取按鍵0         
#define KEY1    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)  //讀取按鍵1
#define KEY2    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)  //讀取按鍵2 
#define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)  //讀取按鍵3(WK_UP) 

uint8_t set_mcu_mode = 0;   //設(shè)置MCU模式,0:運(yùn)行狀態(tài),1:睡眠模式,2:停機(jī)模式,3:待機(jī)模式

//外部中斷0服務(wù)程序
void EXTI0_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(WK_UP == 1)	   //WK_UP按鍵
	{				 
		SystemInit();	 //MCU被喚醒,重新配置系統(tǒng)時(shí)鐘
		set_mcu_mode = 0;
		printf("MCU wake uprn");
	}
	EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中斷標(biāo)志位  
}

//外部中斷2服務(wù)程序
void EXTI2_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(KEY2 == 0)	  //按鍵KEY2
	{
		set_mcu_mode = 1; //需要進(jìn)入睡眠模式
		printf("key2rn");
	}		 
	EXTI_ClearITPendingBit(EXTI_Line2);  //清除LINE2上的中斷標(biāo)志位  
}
//外部中斷3服務(wù)程序
void EXTI3_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(KEY1 == 0)	 //按鍵KEY1
	{				 
		set_mcu_mode = 2; //需要進(jìn)入停機(jī)模式
		printf("key1rn");
	}		 
	EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中斷標(biāo)志位  
}

void EXTI4_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(KEY0 == 0)	 //按鍵KEY0
	{
		set_mcu_mode = 3; //需要進(jìn)入待機(jī)模式
		printf("key0rn");
	}		 
	EXTI_ClearITPendingBit(EXTI_Line4);  //清除LINE4上的中斷標(biāo)志位  
}

//外部中斷初始化
void EXTIX_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
 	EXTI_InitTypeDef EXTI_InitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;

 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOE, ENABLE);//使能PORTA,PORTE時(shí)鐘
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//KEY0-KEY2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //設(shè)置成上拉輸入
 	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,E3,E4
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;//WK_UP KEY-->GPIOA0
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0設(shè)置成輸入,默認(rèn)下拉	  
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA0

  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能復(fù)用功能時(shí)鐘
    //GPIOE2 中斷線以及中斷初始化配置 下降沿觸發(fā)
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line2; //KEY2
  	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  	EXTI_Init(&EXTI_InitStructure);	 	//根據(jù)EXTI_InitStruct中指定的參數(shù)初始化外設(shè)EXTI寄存器
    //GPIOE3 中斷線以及中斷初始化配置 下降沿觸發(fā) 
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line3;  //KEY1
  	EXTI_Init(&EXTI_InitStructure);	  	//根據(jù)EXTI_InitStruct中指定的參數(shù)初始化外設(shè)EXTI寄存器
    //GPIOE4 中斷線以及中斷初始化配置 下降沿觸發(fā)	
  	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
  	EXTI_InitStructure.EXTI_Line=EXTI_Line4; //KEY0
  	EXTI_Init(&EXTI_InitStructure);	  	//根據(jù)EXTI_InitStruct中指定的參數(shù)初始化外設(shè)EXTI寄存器
    //GPIOA0 中斷線以及中斷初始化配置 上升沿觸發(fā) 
 	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); 
  	EXTI_InitStructure.EXTI_Line=EXTI_Line0; //WK_UP KEY
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  	EXTI_Init(&EXTI_InitStructure);		//根據(jù)EXTI_InitStruct中指定的參數(shù)初始化外設(shè)EXTI寄存器

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí)

  	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;				//使能按鍵WK_UP所在的外部中斷通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//搶占優(yōu)先級(jí)2, 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;			//子優(yōu)先級(jí)3
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中斷通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
    NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;				//使能按鍵KEY2所在的外部中斷通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//搶占優(yōu)先級(jí)2, 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;			//子優(yōu)先級(jí)2
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中斷通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
  	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;				//使能按鍵KEY1所在的外部中斷通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//搶占優(yōu)先級(jí)2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;			//子優(yōu)先級(jí)1 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中斷通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器  	  
	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;				//使能按鍵KEY0所在的外部中斷通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//搶占優(yōu)先級(jí)2 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;			//子優(yōu)先級(jí)0 
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;					//使能外部中斷通道
  	NVIC_Init(&NVIC_InitStructure);  	  //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
}

void LED_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);	 //使能PB,PE端口時(shí)鐘

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;				 //LED0-->PB5 端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度為50MHz
	GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根據(jù)設(shè)定參數(shù)初始化GPIOB5
	GPIO_SetBits(GPIOB,GPIO_Pin_5);						 	 //PB5 輸出高
}

int main(void)
{		
	delay_init();	    	//延時(shí)函數(shù)初始化	  
	uart_init(115200);	    //串口初始化為115200
	LED_Init();		  		//初始化與LED連接的硬件接口
	EXTIX_Init();		 	//外部中斷初始化
	
	while(1)
	{	    	
		if(set_mcu_mode > 0)
		{
			switch (set_mcu_mode)
			{
			case 1://進(jìn)入睡眠模式
				printf("Enter sleep modern");
				__WFI();
				break;
			case 2://進(jìn)入停機(jī)模式
				printf("Enter stop modern");
				PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
				break;
			case 3://進(jìn)入待機(jī)模式
				printf("Enter standby modern");
				PWR_EnterSTANDBYMode();
				break;
			default:
				break;
			}
		}
		GPIO_ResetBits(GPIOB, GPIO_Pin_5);	//點(diǎn)亮LED0
		delay_ms(200);	  
		GPIO_SetBits(GPIOB, GPIO_Pin_5);	//關(guān)閉LED0
		delay_ms(200);	
	}
}

示例代碼測(cè)試結(jié)果:

1、MCU正常運(yùn)行,LED0定時(shí)閃爍。
2、按下KEY0,MCU進(jìn)入待機(jī)模式,LED0熄滅,再按下KEY3(WK_UP),MCU被喚醒繼續(xù)運(yùn)行。
3、按下KEY1,MCU進(jìn)入停機(jī)模式,LED0熄滅,再按下KEY3(WK_UP),MCU被喚醒繼續(xù)運(yùn)行。
4、按下KEY2,MCU進(jìn)入睡眠模式,LED0熄滅,再按下KEY3(WK_UP),MCU被喚醒繼續(xù)運(yùn)行。

結(jié)束語(yǔ)

上面的測(cè)試?yán)又皇墙o大家做一個(gè)參考,實(shí)際上需要根據(jù)項(xiàng)目的具體需求去補(bǔ)充很多細(xì)節(jié),比如進(jìn)入低功耗模式的觸發(fā)條件,喚醒的方式,以及進(jìn)入睡眠之前對(duì)外設(shè)的處理,等等,這樣才能保證在實(shí)現(xiàn)功能需求的同時(shí),又能盡可能的把功耗降到最低。
好了,關(guān)于STM32如何進(jìn)入低功耗模式就介紹到這里,如果你們有什么問(wèn)題,歡迎評(píng)論區(qū)留言。

如果這篇文章能夠幫到你,就…懂的。
請(qǐng)?zhí)砑訄D片描述

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
BCM89811B1AWMLG 1 Broadcom Limited Ethernet Transceiver, PACKAGE-36
$13.11 查看
LAN8742AI-CZ 1 Microchip Technology Inc DATACOM, ETHERNET TRANSCEIVER

ECAD模型

下載ECAD模型
$2.57 查看
SN74LVC1G14DBVR 1 Rochester Electronics LLC Inverter,
$0.14 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜