電源對電子設(shè)備的重要性不言而喻,它是保證系統(tǒng)穩(wěn)定運行的基礎(chǔ),而保證系統(tǒng)能穩(wěn)定運行后,又有低功耗的要求。
在很多應(yīng)用場合中都對電子設(shè)備的功耗要求非常苛刻,如某些傳感器信息采集設(shè)備,僅靠小型的電池提供電源,要求工作長達數(shù)年之久,且期間不需要任何維護;由于智慧穿戴設(shè)備的小型化要求,電池體積不能太大導(dǎo)致容量也比較小,所以也很有必要從控制功耗入手,提高設(shè)備的續(xù)行時間。
STM32有專門的電源管理外設(shè)監(jiān)控電源并管理設(shè)備的運行模式,確保系統(tǒng)正常運行,并盡量降低器件的功耗。
- STM32電源管理系統(tǒng)
①備份域
STM32的備份域包括LSE振蕩器、RTC(RTC是一個實時時鐘,當(dāng)主系統(tǒng)掉電后,內(nèi)部RTC專門由一個外部備用電源給它供電,也就是說它有兩個供電源,為RTC備份一個電源是確保整個STM32系統(tǒng)的時間是正常運行的)、備份寄存器及備份SRAM這些器件,這部分的電路可以通過STM32的VBAT引腳獲取供電電源,在實際應(yīng)用中一般會使用3V的鈕扣電池對該引腳供電。
在圖中備份域電路的左側(cè)有一個電源開關(guān)結(jié)構(gòu),它的功能類似圖中的雙二極管,在它的上方連接了VBAT電源,下方連接了VDD主電源(一般為3.3V,紐扣電池電壓為3V),右側(cè)引出到備份域電路中。當(dāng)VDD主電源存在時,由于VDD電壓較高,備份域電路通過VDD供電,當(dāng)VDD掉電時,備份域電路由鈕扣電池通過VBAT供電,保證電路能持續(xù)運行,從而可利用它保留關(guān)鍵數(shù)據(jù)。
②調(diào)壓器供電電路
在STM32的電源系統(tǒng)中調(diào)壓器供電的電路是最主要、最核心的部分,調(diào)壓器為備份域及待機電路以外的所有數(shù)字電路供電,其中包括內(nèi)核、數(shù)字外設(shè)以及RAM,調(diào)壓器的輸出電壓約為1.2V,因而使用調(diào)壓器供電的這些電路區(qū)域被稱為1.2V域。整個電路系統(tǒng)想要實現(xiàn)睡眠模式、待機模式等都離不開調(diào)壓電路。
調(diào)壓器可控制調(diào)節(jié)供電電路使系統(tǒng)運行在“運行模式”、“停止模式”以及“待機模式”下:
運行模式:調(diào)壓器為 1.2 V 域(內(nèi)核、存儲器和數(shù)字外設(shè))提供全功率。
停止模式:1.2V域運行在低功耗狀態(tài),1.2V區(qū)域的所有時鐘都被關(guān)閉,相應(yīng)的外設(shè)都停止了工作,但它會保留內(nèi)核寄存器以及SRAM的內(nèi)容;
待機模式:整個1.2V域都斷電,該區(qū)域的內(nèi)核寄存器及SRAM內(nèi)容都會丟失(備份區(qū)域的寄存器及SRAM不受影響)。
為了提高轉(zhuǎn)換精度,STM32的ADC配有獨立的電源接口,方便進行單獨的濾波。ADC的工作電源使用VDDA引腳輸入,使用VSSA作為獨立的地連接,VREF引腳則為ADC提供測量使用的參考電壓。
- STM32低功耗模式
很多單片機都有低功耗模式,STM32F4 也不例外 ,運行狀態(tài)下的 HCLK 為 CPU 提供時鐘,內(nèi)核執(zhí)行程序代碼。當(dāng) CPU 不需繼續(xù)運行時,可以利用多個低功耗模式來節(jié)省功耗,例如等待某個外部事件時。STM32F4 按功耗由高到低排列具有運行、睡眠、停止和待機四種工作模式。
上電復(fù)位后STM32處于運行狀態(tài)時,當(dāng)內(nèi)核不需要繼續(xù)運行,就可以選擇進入后面的三種低功耗模式降低功耗,這三種模式中,電源消耗不同、喚醒時間不同、喚醒源不同,用戶需要根據(jù)應(yīng)用需求,選擇最佳的低功耗模式。這三種低功耗模式層層遞進,運行的時鐘或芯片功能越來越少,因而功耗越來越低。
1.睡眠模式
在睡眠模式中,僅關(guān)閉了內(nèi)核時鐘,內(nèi)核停止運行,但其片上外設(shè),CM4核心的外設(shè)以及相關(guān)的外設(shè)時鐘全都還照常運行。
有兩種方式進入睡眠模式,它的進入方式?jīng)Q定了從睡眠喚醒的方式,分別是WFI(wait for interrupt,只要有中斷就可以喚醒)和WFE(wait for event),即由等待“中斷”喚醒和由“事件”喚醒。睡眠模式的各種特性見下表:
2.停止模式:
在停止模式中,進一步關(guān)閉了其它所有的時鐘,于是所有的外設(shè)都停止了工作,但由于其1.2V區(qū)域的部分電源沒有關(guān)閉,還保留了內(nèi)核的寄存器、內(nèi)存的信息,所以內(nèi)核和外設(shè)的工作信息并不會丟失,記憶仍留存,喚醒后仍然可以從原狀態(tài)繼續(xù)執(zhí)行。
所以從停止模式喚醒,并重新開啟時鐘后,還可以從上次停止處繼續(xù)執(zhí)行代碼。停止模式可以由任意一個外部中斷線(EXTI),喚醒,注意這里不是任意的中斷。在停止模式中可以選擇電壓調(diào)節(jié)器為開模式或低功耗模式,可選擇內(nèi)部FLASH工作在正常模式或掉電模式。
需要注意的是,停止模式下,關(guān)閉了所有的外設(shè),包括時鐘系統(tǒng)也關(guān)閉了,被喚醒之后首先默認(rèn)選擇HSI內(nèi)部時鐘,如果停止模式之前工作時使用的是HSE外部時鐘,整個系統(tǒng)還需要重新切換為HSE外部時鐘。
3.待機模式
待機模式,它除了關(guān)閉所有的時鐘,還把1.2V區(qū)域的電源也完全關(guān)閉了,也就是說,從待機模式喚醒后,由于沒有之前代碼的運行記錄,只能對芯片復(fù)位,重新檢測boot條件,從頭開始執(zhí)行程序。它有四種喚醒方式,分別是WKUP(PA0)引腳的上升沿,RTC鬧鐘事件,NRST引腳的復(fù)位和IWDG(獨立看門狗)復(fù)位。
- STM32實現(xiàn)睡眠模式
進入方式:內(nèi)核寄存器的SLEEPDEEP = 0 ,然后調(diào)用WFI或WFE指令即可進入睡眠模式;另外若內(nèi)核寄存器的SLEEPONEXIT=0時,進入“立即睡眠”模式,SLEEPONEXIT=1時,進入“退出時睡眠”模式。
實驗內(nèi)容:令指示燈處于工作狀態(tài)表明系統(tǒng)正常運行,之后調(diào)用WFI指令使系統(tǒng)進入睡眠模式,同時指示燈熄滅。使用按鍵中斷喚醒系統(tǒng),同時喚醒時蜂鳴器工作表示系統(tǒng)已喚醒。
實驗步驟:
1.配置RCC
2.配置GPIO管腳
3.配置中斷優(yōu)先級
4.編寫代碼
//main.c
#include "main.h"
#include "stm32f4xx_hal.h"
#include "usart.h"
#include "gpio.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
printf("this is sleep mode testn");
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
while (1)
{
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_RESET);
//指示燈亮表示系統(tǒng)正常運行
HAL_Delay(2000);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_SET); //指示燈滅表示系統(tǒng)進入睡眠模式
HAL_SuspendTick(); //關(guān)閉systick中斷,否則系統(tǒng)會被此中斷喚醒
//注意:關(guān)閉systick中斷后,下面的代碼不能使用HAL_Delay函數(shù),此函數(shù)依賴systick中斷
//調(diào)用封裝好的函數(shù),進入睡眠模式內(nèi)部主要是調(diào)用__WFI()命令
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); //進入睡眠模式
//PWR_MAINREGULATOR_ON這個參數(shù)時保留的一個接口,用來調(diào)節(jié)調(diào)壓器,但是睡眠狀態(tài)下外設(shè)仍然工作
//因此此參數(shù)無效,PWR_SLEEPENTRY_WFI表示通過WFI指令進入睡眠
//進入睡眠模式,下面的代碼不會執(zhí)行
//喚醒后,才會依次執(zhí)行下面的代碼
printf("系統(tǒng)被喚醒!n");
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_RESET); //燈亮表示喚醒
}
}
//gpio.c
//進入中斷處理函數(shù)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0)
{
HAL_ResumeTick(); //回復(fù)systick中斷,否則系統(tǒng)不能使用HAL_Delay
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_SET); //蜂鳴器響200ms表示系統(tǒng)被喚醒
HAL_Delay(200);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_RESET);
}
}
內(nèi)核停止運行時,無法向開發(fā)板燒錄代碼,此時向開發(fā)板燒錄代碼會提示內(nèi)部錯誤。但是可以同時按下開發(fā)板復(fù)位鍵與燒錄按鈕并馬上放開復(fù)位鍵(動作要迅速且流暢),就可以燒錄代碼。
- STM32實現(xiàn)停止模式
停止模式下,內(nèi)核不會工作,外設(shè)也不會工作,但是外設(shè)當(dāng)下的狀態(tài)依舊保留,保留停止前的內(nèi)核寄存器、內(nèi)存的數(shù)據(jù)。因為只是停止了外設(shè)的時鐘,而不會停止供電。外設(shè)不會進一步工作,功耗自然就下降。系統(tǒng)運行的參數(shù)仍然保留,I/O口的狀態(tài)保留為停止前的狀態(tài)。
進入方式:內(nèi)核寄存器的SLEEPDEEP =1,PWR_CR寄存器中的PDDS=0,然后調(diào)用WFI或WFE指令即可進入停止模式;PWR_CR寄存器的LPDS=0時,調(diào)壓器工作在正常模式,LPDS=1時工作在低功耗模式.
喚醒系統(tǒng)首先要恢復(fù)時鐘,默認(rèn)情況下一恢復(fù)首先選擇HSI(內(nèi)部時鐘),如果進入停止模式前一些外設(shè)使用的時HSE(外部時鐘)或者經(jīng)過PLL倍頻后更高速的時鐘喚醒后就會導(dǎo)致由于時鐘頻率很低而無法正常工作。想要系統(tǒng)完全正常工作必須開啟HSE以及PLL單元。
實驗內(nèi)容:令指示燈處于工作狀態(tài)表明系統(tǒng)正常運行,之后調(diào)用WFI指令使系統(tǒng)進入睡眠模式,同時指示燈熄滅。使用按鍵中斷喚醒系統(tǒng),同時喚醒時蜂鳴器工作表示系統(tǒng)已喚醒。喚醒后系統(tǒng)默認(rèn)選擇HSI,重新使能HSE和PLL。
實驗步驟:工程配置與睡眠模式下的配置相同.
編寫代碼:
//main.c
#include "main.h"
#include "stm32f4xx_hal.h"
#include "usart.h"
#include "gpio.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
printf("this is sleep mode testn");
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
while (1)
{
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_RESET); //指示燈亮表示系統(tǒng)正常運行
HAL_Delay(2000);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_SET); //指示燈滅表示系統(tǒng)進入停止模式
//HAL_SuspendTick();不需要關(guān)閉systick中斷,因為要特定的中斷線才能喚醒
//調(diào)用封裝好的函數(shù),進入睡眠模式內(nèi)部主要是調(diào)用__WFI()命令
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); //進入停止模式
//PWR_MAINREGULATOR_ON表示調(diào)壓器處于正常模式
//PWR_LOWPOWERREGULATOR_ON表示調(diào)壓器處于低功耗模式(停止模式),
//PWR_SLEEPENTRY_WFI表示通過WFI指令進入睡眠
//進入停止模式,下面的代碼不會執(zhí)行
//喚醒后,才會依次執(zhí)行下面的代碼
printf("系統(tǒng)被喚醒!n");
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_RESET); //燈亮表示喚醒
}
}
//gpio.c
//編寫時鐘恢復(fù)函數(shù)
void CLK_Resume()
{
//使能HSE
__HAL_RCC_HSE_CONFIG(RCC_HSE_ON);
while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
//等待振蕩器正常工作,振蕩起來
{
//使能PLL
__HAL_RCC_PLL_ENABLE();
while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)//等待PLL正常工作
{
}
//選擇PLL作為系統(tǒng)時鐘
__HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_PLLCLK);
while(__HAL_RCC_GET_SYSCLK_SOURCE() != 0x08 )
{
}
}
//進入中斷處理函數(shù)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0)
{
CLK_Resume(); //恢復(fù)時鐘,打開HSE和PLL
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_SET);
//蜂鳴器響200ms表示系統(tǒng)被喚醒
HAL_Delay(200);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_RESET);
}
}
- STM32實現(xiàn)待機模式
待機模式不僅關(guān)閉內(nèi)核與外設(shè)的時鐘,而且也切斷了電源,這樣系統(tǒng)完全不能工作,狀態(tài)得不到不存,寄存器與內(nèi)存信息丟失。相當(dāng)于復(fù)位,喚醒后從頭開始運行。除復(fù)位引腳、RTC_AF1引腳及WKUP引腳,其它I/O口均工作在高阻態(tài)。
進入方式:內(nèi)核寄存器的SLEEPDEEP =1,PWR_CR寄存器中的PDDS=1,PWR_CR寄存器中的喚醒狀態(tài)位WUF=0,然后調(diào)用WFI或WFE指令即可進入待機模式,喚醒后喚醒狀態(tài)位WUF=1。
待機模式的喚醒方式只能通過一些固定的方式,如:通過WKUP引腳的上升沿,RTC鬧鐘、喚醒、入侵、時間戳事件或NRST引腳外部復(fù)位及IWDG復(fù)位喚醒。
實驗內(nèi)容:令指示燈處于工作狀態(tài)表明系統(tǒng)正常運行,之后調(diào)用WFI指令使系統(tǒng)進入睡眠模式,同時指示燈熄滅。使用按鍵喚醒系統(tǒng),同時喚醒時蜂鳴器工作表示系統(tǒng)已喚醒。事實上,上述睡眠模式與停止模式的工程配置中,按鍵對應(yīng)的PA0就是一個WKUP引腳,因此這里仍然使用按鍵喚醒。
實驗步驟:工程配置與睡眠模式下的配置相同
編寫代碼:
//main.c
#include "main.h"
#include "stm32f4xx_hal.h"
#include "usart.h"
#include "gpio.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
printf("this is stand mode testn");
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
while (1)
{
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_RESET); //指示燈亮表示系統(tǒng)正常運行
HAL_Delay(2000);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_SET); //指示燈滅表示系統(tǒng)進入停止模式
//HAL_SuspendTick();不需要關(guān)閉systick中斷,因為要特定的中斷線才能喚醒
//進入待機模式前,必須使能喚醒管腳,且喚醒狀態(tài)位WUF應(yīng)當(dāng)清0
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); //使能喚醒引腳,f407只有一個喚醒管腳PA0
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);//清除WUF位為0,為1時表示被喚醒
HAL_PWR_EnterSTANDBYMode(); //進入待機模式
//進入待機模式,下面的代碼不會執(zhí)行
//喚醒后,下面的代碼也不會執(zhí)行
printf("系統(tǒng)被喚醒!n");
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_RESET); //燈亮表示喚醒
}
}
//系統(tǒng)進入待機模式后,按下按鍵喚醒,并不會進入中斷,
//而是從頭開始進行工作,是一個復(fù)位操作
//原來的狀態(tài)得不到保存,因此進入待機模式HAL_PWR_EnterSTANDBYMode()
//下面的代碼永遠不會被執(zhí)行到
評論