STM32物联网项目-低功耗模式
低功耗模式
電源框圖
VDD供電區域一般為2V ~ 3.6V,經過電壓調節器可降壓到1.8V給CPU核心、存儲器和內置數字外設供電,為了降低CPU的功耗,
后備供電區域可由電池供電,輸入引腳為VBAT
STM32各種電源
STM32的低功耗模式
STM32F10xxx有三種低功耗模式:
睡眠模式:Cortex?-M3內核停止,所有外設包括Cortex-M3核心的外設,如NVIC、系統時鐘(SysTick)等仍在運行
停止模式:所有的時鐘都已停止
待機模式:1.8V電源關閉
模式從上到下功耗越低,但喚醒條件越嚴格
此外,在運行模式下,可以通過以下方式中的一種降低功耗:
低功耗模式下的自動喚醒(AWU)
低功耗模式下的自動喚醒(AWU)在STM32F1是沒有的,在F4是有的,但F1可以通過RTC鬧鐘事件來喚醒
如下面STM32F4的RTC框圖,就有16位的喚醒自動重載寄存器,可以通過設定值來喚醒
實驗目標
觸摸按鍵1被按下,則系統進入睡眠模式,點擊觸摸按鍵4退出睡眠模式;
觸摸按鍵2被按下,則系統進入停止模式,點擊觸摸按鍵4退出停機模式;
觸摸按鍵3被按下,則進入待機模式,通過復位按鍵退出待機模式;
CubeMX配置
按鍵外部中斷的配置,LED燈作系統的指示作用,拉低WIFI模塊的使能腳,不然模塊會耗電
初始化串口1,用于打印信息
程序
stm32f1xx_hal_pwr.h
下面是進入低功耗模式的三個HAL庫函數,可以直接調用
/* Low Power modes configuration functions ************************************/ void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry); //進入停止模式 void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry); //進入睡眠模式 void HAL_PWR_EnterSTANDBYMode(void); //進入停機模式進入或退出睡眠模式
以WFI進入睡眠模式后,是可以通過任意一個中斷來喚醒的,這里就需要注意了,平時使用的延時函數HAL_Delay()是以SysTick滴答定時器來作為時基的,并且NVIC中默認已經開啟了SysTick的中斷,如果直接在主函數中調用HAL_PWR_EnterSLEEPMode函數進入睡眠模式的話,SysTick滴答定時器的中斷就會立馬喚醒系統,達不到低功耗的效果;所以在進入睡眠模式之前,需要先關閉SysTick的中斷
同理,系統中開啟的用戶中斷也要關閉,如定時器,外部中斷等,可以留某些中斷用于退出睡眠模式
進入睡眠模式函數
這里可以記住幾個函數,有個印象,除了定時器其他的平時都少用,但要用的時候又難找
停止SysTick中斷函數——HAL_SuspendTick()
停止定時器6中斷——HAL_TIM_Base_Stop_IT(&htim6)
關閉外部中斷——HAL_NVIC_DisableIRQ(EXTIx_IRQn)
恢復Systick中斷——HAL_ResumeTick()
恢復(啟動)定時器6中斷——HAL_TIM_Base_Start_IT(&htim6)
恢復外部中斷——HAL_NVIC_EnableIRQ(EXTIx_IRQn)
進入睡眠模式后,通過觸摸按鍵4,觸發外部中斷,可退出睡眠模式
/* * @name Enter_Sleep_Mode * @brief 進入睡眠模式 * @param None * @retval None */ static void Enter_Sleep_Mode() {/*注意:任一中斷都可以將系統從睡眠模式中喚醒*///需要先關閉Systick和定時器6的中斷,否則進入睡眠模式后立馬被喚醒HAL_SuspendTick(); //停止Systick中斷HAL_TIM_Base_Stop_IT(&htim6); //停止定時器6中斷//關閉外部中斷0至2,只允許觸摸按鍵4外部中斷退出睡眠模式HAL_NVIC_DisableIRQ(EXTI0_IRQn);HAL_NVIC_DisableIRQ(EXTI1_IRQn);HAL_NVIC_DisableIRQ(EXTI2_IRQn);//以WFI進入睡眠模式,可以被任一中斷喚醒HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON,PWR_SLEEPENTRY_WFI);//恢復中斷HAL_ResumeTick(); //恢復Systick中斷HAL_TIM_Base_Start_IT(&htim6); //恢復定時器6中斷//恢復外部中斷0至2HAL_NVIC_EnableIRQ(EXTI0_IRQn);HAL_NVIC_EnableIRQ(EXTI1_IRQn);HAL_NVIC_EnableIRQ(EXTI2_IRQn); }進入睡眠模式函數的參數說明
/*** @brief Enters Sleep mode.* @note In Sleep mode, all I/O pins keep the same state as in Run mode.* @param Regulator: Regulator state as no effect in SLEEP mode - allows to support portability from legacy software* @param SLEEPEntry: Specifies if SLEEP mode is entered with WFI or WFE instruction.* When WFI entry is used, tick interrupt have to be disabled if not desired as * the interrupt wake up source.* This parameter can be one of the following values:* @arg PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction* @arg PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction* @retval None*/ void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry) {/* Check the parameters *//* No check on Regulator because parameter not used in SLEEP mode *//* Prevent unused argument(s) compilation warning */UNUSED(Regulator);assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry));........ }進入睡眠模式的HAL庫函數中,參數Regulator表示電壓調節器,而睡眠模式下的電壓調節器是始終打開的,那為什么還有這個參數呢?
原因:可以看參數Regulator的英文說明,Regulator state as no effect in SLEEP mode - allows to support portability from legacy software,說的是電壓調節器的狀態在睡眠模式下是沒有影響的,無論傳哪個符合的參數進去,電壓調節器還是會打開,定義這個參數只是為了兼容以前的代碼;同時在函數內部也不對Regulator參數進行檢查,該參數在睡眠模式下無效
進入和退出停機模式
因為停機模式只能由外部中斷來退出,所以可以不停止SysTick定時器中斷和定時器中斷,在函數中留個按鍵4外部中斷用來退出停機模式,其他外部中斷都禁止掉
/* * @name Enter_Stop_Mode * @brief 進入停機模式 * @param None * @retval None */ static void Enter_Stop_Mode() {/*注意:外部中斷可以將系統從停機模式中喚醒*///關閉外部中斷0至2,只允許觸摸按鍵4外部中斷退出停止模式HAL_NVIC_DisableIRQ(EXTI0_IRQn);HAL_NVIC_DisableIRQ(EXTI1_IRQn);HAL_NVIC_DisableIRQ(EXTI2_IRQn);//以WFI、電壓調節器低功耗模式進入停機模式HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI);//退出停機模式時,HSI RC振蕩器被選為系統時鐘//重新選擇系統時鐘為HSESystemClock_Config();//開啟外部中斷HAL_NVIC_EnableIRQ(EXTI0_IRQn);HAL_NVIC_EnableIRQ(EXTI1_IRQn);HAL_NVIC_EnableIRQ(EXTI2_IRQn); } void HAL_PWR_EnterSTOPMode(uint32_t Regulator,uint8_t STOPEntry)進入停機模式的函數中,參數Regulator(內部調壓器的)有兩種選擇,
一種是:PWR_MAINREGULATOR_ON(正常模式)
另一種是:PwR_LOWPOWERREGULATOR_ON(低功耗模式)
兩種選擇的區別,正常模式恢復比較快,低功耗模式功耗較低,但啟動時間會長點,可根據產品來選擇,如果產品要求啟動時間要快,則選擇正常模式,如果對啟動時間沒有要求,則選擇低功耗模式
注意:當一個中斷或喚醒事件導致退出停止模式時,HSI RC振蕩器被選為系統時鐘,所以從停止模式退出后,要重新設置系統時鐘,需要調用SystemClock_Config()函數
進入和退出待機模式
待機模式可實現系統的最低功耗。該模式是在Cortex-M3深睡眠模式時關閉電壓調節器。整個 1.8V供電區域被斷電。PLL、HSI和HSE振蕩器也被斷電。SRAM和寄存器內容丟失。只有備份的寄存器和待機電路維持供電
直接調用庫函數進入待機模式,此時芯片的IO引腳處于高阻態,并不受芯片控制,所以那些模塊的電最好都先斷掉
/* * @name Enter_Standby_Mode * @brief 進入待機模式 * @param None * @retval None */ static void Enter_Standby_Mode() {/*注意:系統復位鍵可以將系統從待機模式中喚醒*///待機模式直接調用庫函數即可HAL_PWR_EnterSTANDBYMode(); }System.c
運行函數中延時1s,然后每隔10ms檢測低功耗模式標志位是否被置位,是則調用函數進入對應的低功耗模式
/* * @name Run * @brief 系統運行 * @param None * @retval None */ static void Run() {uint8_t i;//延時1s,期間每隔10ms檢測是否需要進入低功耗模式for(i=0;i<100;i++){//進入睡眠模式if(LowPower.Enter_Sleep_Mode_Flag == TRUE){LowPower.Enter_Sleep_Mode_Flag = FALSE;printf("系統進入睡眠模式,通過按鍵4喚醒\r\n");LowPower.Enter_Sleep_Mode();}//進入停機模式if(LowPower.Enter_Stop_Mode_Flag == TRUE){LowPower.Enter_Stop_Mode_Flag = FALSE;printf("系統進入停機模式,通過按鍵4喚醒\r\n");LowPower.Enter_Stop_Mode();}//進入待機模式if(LowPower.Enter_Standby_Mode_Flag == TRUE){LowPower.Enter_Standby_Mode_Flag = FALSE;printf("系統進入待機模式,通過復位按鍵喚醒\r\n");printf("待機模式,外設不受STM32控制,系統功耗可能增加!\r\n");printf("如WiFi模塊,可以用鑷子將EN管腳短接到地!\r\n");LowPower.Enter_Standby_Mode();}//延時HAL_Delay(10);}printf("系統正常運行\r\n"); }CallBack.c
在中斷回調函數中判斷觸摸按鍵是否被按下,是則將低功耗模式標志位置位,然后主函數中就可以調用低功耗函數讓系統進入低功耗模式
/* * @name HAL_GPIO_EXTI_Callback * @brief 外部中斷回調函數 * @param GPIO_Pin:觸發外部中斷的引腳 * @retval None */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {uint8_t i;if(GPIO_Pin == KEY1_Pin){printf("檢測到按鍵1被按下\r\n");LowPower.Enter_Sleep_Mode_Flag = TRUE;LED.LED_Fun(LED2,LED_ON);for(i=0;i<100;i++){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) == GPIO_PIN_SET){LowPower.Enter_Sleep_Mode_Flag = FALSE;printf("按鍵1提前釋放,系統正常運行\r\n");break;}}LED.LED_Fun(LED2,LED_OFF);}if(GPIO_Pin == KEY2_Pin){printf("檢測到按鍵2被按下\r\n");LowPower.Enter_Stop_Mode_Flag = TRUE;LED.LED_Fun(LED2,LED_ON);for(i=0;i<100;i++){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_SET){LowPower.Enter_Stop_Mode_Flag = FALSE;printf("按鍵2提前釋放,系統正常運行\r\n");break;}}LED.LED_Fun(LED2,LED_OFF);}if(GPIO_Pin == KEY3_Pin){printf("檢測到按鍵3被按下\r\n");LowPower.Enter_Standby_Mode_Flag = TRUE;LED.LED_Fun(LED2,LED_ON);for(i=0;i<100;i++){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin) == GPIO_PIN_SET){LowPower.Enter_Standby_Mode_Flag = FALSE;printf("按鍵3提前釋放,系統正常運行\r\n");break;}}LED.LED_Fun(LED2,LED_OFF);} }實驗效果
總結
以上是生活随笔為你收集整理的STM32物联网项目-低功耗模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “我的世界开服侠”使用教程
- 下一篇: 四国军棋界面Swing/AWT的代码