項目背景
設備具備電池、電源適配器兩種供電方式,實現出廠時最低功耗(即進入待機模式),到用戶開始使用時需要手動喚醒,開始復位運行。在檢測到設備是交流供電時,設備全速運行;電測到是電池供電時,定時採集數據,採集完畢進入停止模式,定時器喚醒等待下次數據採集。(stm32f103ret6)
備註:本節只記錄待機模式的進入和喚醒,停止模式的實現方式見STM32進入STOP模式並喚醒實驗總結
用待機模式的理由及與停止模式的區別
- 選用待機模式
設備出廠,電池裝在電路板上,封閉在模具當中,在到用戶開始使用之前,必須保持最低功耗。停止模式下CPU電流消耗在20uA左右,而待機模式的電流消耗只有2uA。
- 和停止模式的區別
因爲SRAM和寄存器的內容會保存,即能PC指針能記錄程序當前運行的位置,從停止模式喚醒時,能繼續沿着到時進入停止模式處繼續往下運行。(故運行時,設備檢測到是電池供電時,選用停止模式:採集完數據進入停止模式,2小時後(根據需求自定義)定時喚醒採集,依此循環)
SRAM和寄存器內容不會保存,即待機模式喚醒相當於系統復位,從頭運行(設備測試完成,整機入庫時,通過外部按鍵等方式觸發進入待機模式)
待機模式實現
進入待機模式三個步驟說明:
1.將系統控制寄存器第二位置1,當進入深度睡眠時,允許停止系統時鐘(系統控制寄存器參考《Cortex-M3權威指南》)
2.使能PWR_CR的PDDS位,使得深度休眠時進入待機模式
3.清除WUF喚醒標誌(WUF標誌由硬件置位,當系統是WKUP喚醒復位而不是上電等復位時會置位。應用中可以用來讀取PWR_CSR的WUF位是否爲1來判斷系統復位是不是待機喚醒)
4.
以上三個步驟由庫函數PWR_EnterSTANDBYMode()實現
進入待機模式
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();
}
//數據採集、發送
//進入停止模式
//定時從停止模式喚醒
}
}