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