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