STM32低功耗——轉載
本文主要解讀STM32低功耗模式的機制,並不側重STM32低功耗的程式實現,而且藉助STM32韌體庫實現STM32低功耗會變的非常簡單。
一、STM32晶片效能
使用晶片型號:stm32,CORTEX -M0.封裝TSSOP20.
執行模式:內部時鐘(HSI),系統時鐘頻率採用48MHZ。
工作電壓:3.3V
晶片具體引數如下:
二、晶片功耗
功耗:
晶片工作模式:
工作模式:外設正常執行,核心CPU及SRAM供電,未使用外設的時鐘預設關閉。
睡眠模式:只有CPU停止工作,各個外設正常工作,依靠任何中斷/事件喚醒。
停機模式:1.8V供電區域時鐘被停止,
待機模式:1.8V供電區域被時鐘停止,內部HSI,PLL,外部時鐘HSE均關閉,同時電壓檢測器也可進入低功耗模式,SRAM和不屬於待機電路的暫存器也被斷電關閉,此時即使是外部中斷(EXTI)也不能將其喚醒,只能通過復位(外部復位,看門狗復位)、喚醒引腳、RTC時鐘來喚醒。
注意:無論是在停止模式 還是待機模式下,RTC和IWDG及其時鐘源不會被關閉。
各個模式功耗:
功耗計算方式:功耗=工作電壓*工作電流。
I/O模組損耗:
靜態損耗:
內部上下拉電阻損耗:這部分損耗主要取決於內部電阻的大小,一般為了降低內部電阻損耗常常需要降低電阻兩端電壓,若引腳為低電壓則採用下拉電阻,若引腳為高電壓則採用上拉電阻。
I/O額外損耗:當引腳設為輸入I/O時,用來區分電壓高低的斯密特觸發器電路會產生一部分消耗,為此可將引腳設為模擬輸入模式。
動態損耗:對於懸浮的引腳,由於其電壓不穩定會產生外部電磁干擾和損耗,因此必須把懸浮引腳設為模擬模式或輸出模式,引腳電壓的切換會對外部和內部電容負載產生動態損耗,其損耗與電壓切換頻率和負載電容有關。具體損耗值如下:
三、CORTEX-M0低功耗功能、指令、相關暫存器
CORREX核心支援低功耗模式有
睡眠模式:CPU時鐘停止,對應stm32睡眠模式
深度睡眠模式:系統時鐘停止,PLL,FLASH 關閉,對應stm32停機模式。
進入睡眠模式:
當CPU處理完中斷後軟體必須能使其進入睡眠模式,當CPU執行WFI指令,其將會立即進入睡眠模式,當異常產生或中斷被掛起時,其立即被喚醒。
當CPU執行WFE指令時,它首先會檢查對應的事件標誌位,當事件標誌暫存器為0時進入睡眠模式,否則將暫存器事件標誌清0並繼續執行程式。事件標誌可由外部事件標誌或SEV指令產生。
返回方式:通過設定核心SCB暫存器的Sleep-on-exit位,可以選擇系統被喚醒執行完中斷服務程式後進入主執行緒模式後是否立即進入睡眠模式。
從睡眠中喚醒:
WFI喚醒或sleep-on-exit:
一般來說,使能的異常可以喚醒核心。對於一些系統,在喚醒後執行中斷處理程式前需要先執行重新恢復的任務,則首先需要遮蔽所有中斷(PRIMASK=1),中斷髮生後核心被喚醒但不執行中斷處理,待執行完恢復任務後再將PRIMASK設為0,此後執行中斷處理任務。
WFE喚醒:
使能異常可以喚醒核心。外部事件或SEV指令傳送的事件也可喚醒核心。
注意:當SCR的SEVONPEND設定為1時,任何使能/非使能中斷或事件都可喚醒核心。
中斷喚醒控制器(WIC):
WIC只有在SCR暫存器DEEPSLEEP位設為1時才能使能,WIC不可程式設計也沒有相關的控制暫存器,它僅與硬體訊號有關,當進入深睡眠時核心大部分模組被關閉,系統計數器也被關閉,因此當核心被喚醒時需要較多的時間恢復到睡眠前的狀態並處理中斷。
外部事件輸入:可在WFE模式下喚醒核心。
相關指令:
WFE 等待事件,若無事件則睡眠,中斷、事件喚醒
WFI 等待中斷,立即進入睡眠,中斷喚醒
SEV 軟體傳送一個事件,在核系統中可喚醒另一個核心。
微控制器軟體介面標準:
由指令對應的C語言介面:
//core_cmInstr.h
void __WFE(void) // Wait for Event
void __WFI(void) // Wait for Interrupt
void __SEV(void) // Send Event
相關暫存器:
SCR暫存器:
SEVONPEND:
0: 只有使能的中斷或事件才能喚醒核心。
1: 任何中斷和事件都可以喚醒核心。
SLEEPDEEP:
0: 低功耗模式為睡眠模式。
1: 進入低功耗時為深度睡眠模式。
SLEEPONEXIT:
0: 被喚醒進入執行緒模式後不再進入睡眠模式。
1: 被喚醒後執行完相應的中斷處理函式後進入睡眠模式。
四、STM32時鐘管理
執行模式下可通過關閉和降低相關外設的時鐘頻率來減少功耗。
APB 外設時鐘和DMA時鐘可用軟體禁止。
睡眠模式停止CPU時鐘。在CPU睡眠中儲存器介面時鐘(Flash和RAM介面)可被停止。當連線到APB所有外設的時鐘禁止後,當進入睡眠期間AHB 到APB橋時鐘由CPU的硬體關閉。
CPU進入停止模式時停止V18域、PLL、HSI、HSI14和HSE振盪器的時鐘。
HDMI CEC, USART1 和I2C1 即使在MCU 進入停止模式下仍有能力開啟HIS振盪器 (假如HIS被選為這些外設的時鐘)。
在LSE振盪器已使能的情況下,HDMI CEC 和 USART1 當在系統進入停止模式下也可由LSE振盪器驅動 (假如LSE被選為這些外設時鐘)。但是這些外設沒有開啟LSE振盪器的能力。
CPU進入待機模式時停止V18域、PLL、HSI、HSI14和HSE振盪器的時鐘。
當設定DBGMCU_CR暫存器中的DBG_STOP 或DBG_STANDBY位,那麼CPU在相應的深度睡眠模式下也可以具有除錯功能。
當系統由中斷(停止模式)或復位(待機模式)喚醒後,HSI振盪器被選為系統時鐘(不管進入停止模式或待機模式前選用的是何種時鐘)。
假如當前正在進行快閃記憶體程式設計,只有在快閃記憶體程式設計全部完成之後才會進入深度睡眠模式(深度睡眠延後)。若當前正在使用APB域,那麼只有全部完成APB域的操作後才進入深度睡眠模式。
五、STM32低功耗設定
STM32工作模式主要有執行、睡眠、停止、待機4種模式,前面已介紹過。詳細見第二節。
供電框圖
由上圖可以看到整個stm32晶片的供電圖,類比電路部分採用VDDA獨立供電,各個部分可以獨立被關斷或開啟。備份電路部分由電池供電,主要有RTC時鐘及相關的備份暫存器,VDD掉電後可由電池供電,對於沒有VBAT引腳的晶片,其電源直接與VDD相連。核心部分分為1.8V工作域和VDD工作域,1.8V工作域主要有核心、儲存、外設部分,VDD供電域主要有I/O、待機電路(喚醒電路,獨立看門狗)、電壓調節器(Voltage Regulator)。
電壓調節器
器件復位後電壓調節器總是開啟著的,其根據應用模式有三種不同的工作模式。
執行模式:調節器以全功耗模式為域 (核心,記憶體和數字外設) 提供1.8V電源。
停止模式:調節器以低功耗模式為保持暫存器及SRAM資料部分域提供1.8V的電源。
待機模式:調節器斷電,除了待機電路及備份域電路外,暫存器和SRAM的內容全部丟失。
相關暫存器介紹:
1,cortex-mo中的SCR暫存器
SEVONPEND:
0: 只有使能的中斷或事件才能喚醒核心。
1: 任何中斷和事件都可以喚醒核心。
SLEEPDEEP:
0: 低功耗模式為睡眠模式。
1: 進入低功耗時為深度睡眠模式。
SLEEPONEXIT:
0: 被喚醒進入執行緒模式後不再進入睡眠模式。
1: 被喚醒後執行完相應的中斷處理函式後進入睡眠模式。
2,電源控制暫存器PWR_CR
其中與低功耗有關的控制位:
CSBF: 清除待機標誌,該位始終讀出為0,寫1清除待機標誌。
CWUF: 清除喚醒標誌,該位始終讀出為0。寫1清除喚醒標誌。
PDDS: 掉電深睡眠
0: 當CPU進入深睡眠時進入停機模式,調壓器的狀態由LPDS位控制。
1: 當CPU進入深睡眠時進入待機模式。
LPDS: 深睡眠下的低功耗
0: 在停機模式下電壓調節器開啟
1: 在停機模式下電壓調節器處於低功耗模式
3,電源控制/狀態暫存器(PWR_CSR)
EWUP2/EWUP1: 使能WKUP2或EWUP1引腳。
0: WKUP1/2 引腳作為通用IO口。WKUP1引腳上的事件不能將CPU從待機模式喚醒。
1: WKUP1/2引腳用於將CPU從待機模式喚醒,WKUP1引腳被強置為輸入下拉的配置(WKUP1引腳上的上升沿將系統從待機模式喚醒)。
SBF: 待機標誌
該位由硬體設定,只能設定電源控制暫存器PWR_CR的CSBF位清除。
0:系統不在待機模式
1:系統進入待機模式
WUF: 喚醒標誌
由硬體設定,只能設定電源控制暫存器PWR_CR的CWUF位清除。
0: 沒有喚醒事件發生
1: 從WKUP或RTC鬧鐘產生一個喚醒事件
注意:當WKUP引腳已經是高電平時,在(通過設定EWUP位)使能WKUP引腳時,會檢測到一個額外喚醒的事件。
低功耗模式的進入與退出問題
1、睡眠模式
進入睡眠模式:
當STM32在執行狀態時,執行WFI或WFE指令可進入睡眠模式。
條件:SLEEPDEEP=0,設為睡眠模式。此時CPU時鐘被停止。
若令被喚醒的STM32執行完中斷處理任務後進入睡眠模式,則可將SLEEPONEXIT設為1.
退出睡眠模式:
執行WFI指令進入睡眠,可通過使能中斷喚醒。執行WFE指令進入睡眠可由事件喚醒,CPU時鐘開啟。產生事件的兩種方式:
配置一個外部或內部EXTI線做為事件模式。
使能外設中斷但不使能NVIC中斷,同時將SEVONPEND設為1,此時任何中斷和事件都可以喚醒核心,此時必須清除NVIC和外設的中斷標誌以免喚醒後出錯。
2、停止模式
進入停止模式:
進入停止模式後1.8電壓區域時鐘被停止,PLL,HSI,HSE被關閉,但SRAM和暫存器正常供電。進入停止模式方法:首先確定所有中斷/事件標誌被清除否則不會進入停止模式,關閉ADC\DAC電源,將SLEEPDEEP設為深睡眠模式,在深睡眠後選擇進入停機模式(PDDS=0),可關閉或開啟電壓調節器(LPDS),執行WFI或WFE指令進入停機模式。
退出停止模式:
一個使能的外部中斷或外部事件可喚醒STM32。SMT32被喚醒後系統時鐘被設為HSI。因此在喚醒後還需軟體恢復時鐘設定,並清除相關的低功耗標誌。
3、待機模式
進入待機模式:
進入SRAM和暫存器內容丟失,進入條件:將SLEEPDEEP設為深睡眠模式,在深睡眠後選擇進入待機模式(PDDS=1),關閉電壓調節器(LPDS),執行WFI或WFE指令進入待機模式。
在待機模式下,除了復位引腳(始終有效)、當配置為防侵入或校準輸出時的TAMPER 引腳、使能的喚醒(WKUP)引腳外,所有的I/O口線處於高阻態。因此進入待機模式前不需要再特意配置引腳的低功耗特性。
退出待機模式:
IWDG復位,WKUP引腳上的上升沿或RTC 鬧鐘事件可喚醒STM32,當退出待機模式時除了電源控制/狀態暫存器(PWR_CSR)外所有暫存器復位,整個系統被複位。
4、低功耗模式下的RTC自動喚醒
RTC可以在不需要依賴外部中斷的情況下喚醒低功耗模式下的微控制器(自動喚醒模式)。RTC提供一個可程式設計的時間基數,用於週期性從停止或待機模式下喚醒。
從停止模式下喚醒,必須進行如下操作:
配置外部中斷線17為上升沿觸發。
配置RTC使其可產生RTC鬧鐘事件。
從待機模式中喚醒,不必配置外部中斷線17。
5、除錯模式
預設情況下,如果在進行除錯微處理器時,使微處理器進入停止或待機模式,將失去除錯連線。這是因為Cortex-M0的核心失去了時鐘。通過設定DBGMCU_CR暫存器中的某些配置位,可以在使用低功耗模式下除錯軟體。
六、低功耗模式總結
降低STM32功耗方法主要有:
關閉不需要的外設、降低STM32的系統頻率。
合理設定I/O降低I/O靜態和動態損耗。
進入低功耗模式。
恢復到正常執行狀態:
睡眠模式由中斷或事件喚醒,喚醒後可清除喚醒標誌。
停止模式:喚醒後需恢復時鐘設定,並將改動的I/O設定恢復。
待機模式:喚醒後系統被恢復,隨後系統被複位,可清除待機標誌。
七、韌體庫使用
主要檔案:
stm32f0xx_rcc.c,stm32f0xx_gpio.c,stm32f0xx_pwr.c
時鐘及I/O設定相關函式(部分):
void RCC_XXXPeriphClockCmd(X,X) ; //用於使能和關閉外設時鐘
void SystemInit (void);//系統初始化設定時鐘
GPIO_Init(GPIOX, &GPIO_InitStructure);//設定相關引腳
低功耗函式(部分):
//喚醒引腳配置
void PWR_WakeUpPinCmd(uint32_t PWR_WakeUpPin, FunctionalState NewState);
//讀/清除暫存器狀態標識
FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);
void PWR_ClearFlag(uint32_t PWR_FLAG);
進入低功耗模式:
void PWR_EnterSleepMode(uint8_t PWR_SLEEPEntry);
Void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);
void PWR_EnterSTANDBYMode(void);
函式解析:
下面是一個進入停機模式的函式,此函式功能和使用方法在註釋部分已經非常明確。通過原始碼可以看出SMT32在停機模式下暫存器的設定情況。呼叫此函式STM32可進入低功耗模式。
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_PWR_REGULATOR(PWR_Regulator));
assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
/* Select the regulator state in STOP mode ———————————*/
tmpreg = PWR->CR;
/* Clear PDDS and LPDSR bits */
tmpreg &= CR_DS_MASK;
/* Set LPDSR bit according to PWR_Regulator value */
tmpreg |= PWR_Regulator;
/* Store the new value */
PWR->CR = tmpreg;
/* Set SLEEPDEEP bit of Cortex-M0 System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
/* Select STOP mode entry ————————————————–*/
if(PWR_STOPEntry == PWR_STOPEntry_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__WFE();
}
/* Reset SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
}