STM32進入Standby模式並喚醒

項目背景

設備具備電池、電源適配器兩種供電方式,實現出廠時最低功耗(即進入待機模式),到用戶開始使用時需要手動喚醒,開始復位運行。在檢測到設備是交流供電時,設備全速運行;電測到是電池供電時,定時採集數據,採集完畢進入停止模式,定時器喚醒等待下次數據採集。(stm32f103ret6)
備註:本節只記錄待機模式的進入和喚醒,停止模式的實現方式見STM32進入STOP模式並喚醒實驗總結

用待機模式的理由及與停止模式的區別

  1. 選用待機模式

設備出廠,電池裝在電路板上,封閉在模具當中,在到用戶開始使用之前,必須保持最低功耗。停止模式下CPU電流消耗在20uA左右,而待機模式的電流消耗只有2uA。

  1. 和停止模式的區別

圖
因爲SRAM和寄存器的內容會保存,即能PC指針能記錄程序當前運行的位置,從停止模式喚醒時,能繼續沿着到時進入停止模式處繼續往下運行。(故運行時,設備檢測到是電池供電時,選用停止模式:採集完數據進入停止模式,2小時後(根據需求自定義)定時喚醒採集,依此循環)

圖2
SRAM和寄存器內容不會保存,即待機模式喚醒相當於系統復位,從頭運行(設備測試完成,整機入庫時,通過外部按鍵等方式觸發進入待機模式)
圖3

待機模式實現

圖4
進入待機模式三個步驟說明:

1.將系統控制寄存器第二位置1,當進入深度睡眠時,允許停止系統時鐘(系統控制寄存器參考《Cortex-M3權威指南》)
圖5
2.使能PWR_CR的PDDS位,使得深度休眠時進入待機模式
3.清除WUF喚醒標誌(WUF標誌由硬件置位,當系統是WKUP喚醒復位而不是上電等復位時會置位。應用中可以用來讀取PWR_CSR的WUF位是否爲1來判斷系統復位是不是待機喚醒)
4.
以上三個步驟由庫函數PWR_EnterSTANDBYMode()實現
圖5

進入待機模式
void Standby_Entering(void)
{
	RCC_APB2PeriphResetCmd(0x01fc, DISABLE);		//準備進入待機模式,復位所有IO,降低功耗(參照手冊,根據需要復位對應IO)
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//需要配置電源控制寄存器,所以使能時鐘,否則不能正常使用命令進入待機狀態和喚醒
	PWR_WakeUpPinCmd(ENABLE);					//使能WKUP引腳喚醒功能,否則WKUP引腳上升沿不能喚醒
	PWR_EnterSTANDBYMode();					//進入待機模式
}

void Standby_Configure(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure;
	//EXTI_InitTypeDef  EXTI_InitStructure;
	//NVIC_InitTypeDef NVIC_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPD;
	GPIO_Init(WAKEUP_PORT, &GPIO_InitStructure);

/*如果PA0只是用於喚醒,這部分可以不要,喚醒不是中斷,中斷控制器已經停止工作,如果正常模式下需要用到,可根據需要添加,這時候是中斷事件
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;   
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    
	NVIC_Init(&NVIC_InitStructure); 
	*/
}
中斷處理(注:喚醒之後相當於復位,不會執行中斷函數裏的內容)
void EXTI0_IRQHandler(void)
{
	EXTI_ClearITPendingBit(EXTI_Line0);		//清除LINE0上的中斷標誌位
}

void main(void)
{
	...
	Standby_Configure();
	...
	//讀取PWR_CSR的WUF位檢測復位來源,這也就是爲什麼在進入待機模式之前需要清除WUF喚醒標誌,這樣檢測到喚醒標誌就能確定發生了喚醒復位
	
	if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET)//從待機喚醒後,除了電源控制/狀態寄存器(PWR_CSR),所有寄存器被複位
	{
		//是待機喚醒復位,可幫助調試
	}
	else
	{
		//上電覆位、軟件復位等非喚醒復位
	}
	while(1)
	{
		if(外部按鍵標誌)				//根據硬件和個人需求確定什麼時候進入待機模式
		{
			Standby_Entering();
		}

		//數據採集、發送
		//進入停止模式
		//定時從停止模式喚醒	
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章