【STM32】PWR電源控制
- 一、PWR
- 1.1 PWR簡介
- 1.2 STM32電源框圖
- 1.3 上電覆位和掉電覆位
- 1.4 可編程電壓監測器
- 二、低功耗模式
- 2.1 睡眠模式
- 2.2 停止模式
- 2.3 待機模式
一、PWR
1.1 PWR簡介
- PWR(Power Control)電源控制
- PWR負責管理STM32內部的電源供電部分,可以實現可編程電壓監測器和低功耗模式的功能
- 可編程電壓監測器(PVD)可以監控VDD電源電壓,當VDD下降到PVD閥值以下或上升到PVD閥值之上時,PVD會觸發中斷,用於執行緊急關閉任務
- 低功耗模式包括睡眠模式(Sleep)、停機模式(Stop)和待機模式(Standby),可在系統空閒時,降低STM32的功耗,延長設備使用時間
1.2 STM32電源框圖
1. 供電區域劃分
圖中把STM32的電源系統劃分為四個核心供電區域,分別對應不同的功能模塊,實現電源的分級管理與針對性供電:
- VDDA供電區域
- VDD供電區域
- 1.8V供電區域
- 後備供電區域(VBAT)
2. 各區域功能與模塊解析
1) VDDA供電區域
- 供電對象:A/D轉換器、温度傳感器、復位模塊、PLL(鎖相環)。
- 電源範圍:
VREF-(可與VSSA共地)到VREF+,電壓範圍從2.4V起至VDDA。 - 設計邏輯:該區域為模擬/混合信號模塊供電,需保證電源的穩定性(如ADC對電源噪聲敏感),因此獨立劃分供電,避免數字電路的干擾。
2)VDD供電區域
- 子模塊1:I/O電路
負責CPU芯片的輸入輸出接口供電,是數字信號與外部設備交互的“門户”。 - 子模塊2:待機電路(喚醒邏輯、IWDG)
- 喚醒邏輯:支持芯片從低功耗待機模式快速喚醒,保障系統響應速度。
- IWDG(獨立看門狗):是一種硬件監控機制,若程序運行異常(如死循環),IWDG會觸發復位,保證系統可靠性。
- 子模塊3:電壓調節器
是電源管理的核心單元之一,負責將VDD的輸入電壓轉換為1.8V,為“1.8V供電區域”供電。
3)1.8V供電區域
- 供電對象:CPU核心、存儲器、內置數字外設。
- 設計邏輯:CPU和高速數字模塊對電源電壓精度、功耗敏感,通過電壓調節器將VDD降壓到1.8V,既滿足性能需求,又能降低功耗。
4)後備供電區域(VBAT)
- 供電對象:LSE 32K晶體振盪器、後備寄存器、RCC BDCR寄存器、RTC(實時時鐘)。
- 設計邏輯:該區域由備用電池(VBAT)供電,即使主電源(VDD)掉電,也能維持RTC計時、後備寄存器數據存儲,保障系統的時間連續性和關鍵數據不丟失。
1.3 上電覆位和掉電覆位
- 復位信號(Reset):低電平表示芯片處於復位狀態,高電平表示覆位釋放,芯片開始運行。
- 上電階段:電源電壓從 0 上升,當超過 POR 閾值並經過滯後時間後,復位信號釋放,芯片開始初始化運行。
- 掉電階段:電源電壓下降,當低於 PDR 閾值時,復位信號拉低,芯片進入復位狀態,防止電壓不足時運行異常。
- 上電時超過POR才不會復位,掉電時低於PDR就開始復位。
- 通過硬件級的復位機制,保證芯片在 “上電時電源穩定後才啓動”“掉電時提前復位以保護數據”,提升系統可靠性。
1.4 可編程電壓監測器
- 電壓上升階段:當 VDD/V DDA 電壓上升超過 PVD 閾值時,PVD 輸出電平翻轉。
- 電壓下降階段:當 VDD/V DDA 電壓 下降低於(PVD 閾值 - 100mV 遲滯) 時,PVD 輸出電平再次翻轉。
- 可用於提前檢測電源電壓異常(如掉電預警),讓系統有時間執行備份數據、進入低功耗等保護操作,提升系統可靠性。用户可通過配置寄存器選擇不同的 PVD 閾值,適配不同應用場景的電源監測需求。
二、低功耗模式
- 睡眠模式:是“輕量級”低功耗模式,僅暫停CPU運行,外設和時鐘基本保持,用於短時間待機且需快速響應的場景。
- 停機模式:深度降低功耗,關閉大部分時鐘和1.8V區域供電,需外部中斷喚醒,適用於對功耗敏感、可容忍稍慢喚醒速度的場景。
- 待機模式:是最深的低功耗模式,幾乎關閉所有電源和時鐘(僅後備區域保持),需特定喚醒源(如WKUP引腳、RTC),用於極致功耗優化的場景。
|
低功耗模式
|
CPU狀態
|
內核外設/寄存器
|
系統時鐘
|
大部分外設狀態
|
特殊保持的模塊
|
|
睡眠模式(Sleep)
|
停止運行
|
保持(數據不丟)
|
保持(可配置)
|
正常運行(可配置關閉)
|
無(或僅關閉未使用外設)
|
|
停機模式(Stop)
|
停止運行
|
保持(數據不丟)
|
關閉
|
斷電(寄存器數據保持)
|
RTC、IWDG(若使能)
|
|
待機模式(Standby)
|
完全斷電
|
丟失(全部重置)
|
幾乎全部關閉
|
幾乎全部斷電
|
RTC、LSE、後備寄存器、IWDG(若使能)
|
2.1 睡眠模式
- 執行完WFI/WFE指令後,STM32進入睡眠模式,程序暫停運行,喚醒後程序從暫停的地方繼續運行
- SLEEPONEXIT位決定STM32執行完WFI或WFE後,是立刻進入睡眠,還是等STM32從最低優先級的中斷處理程序中退出時進入睡眠
- 在睡眠模式下,所有的I/O引腳都保持它們在運行模式時的狀態
- WFI指令進入睡眠模式,可被任意一個NVIC響應的中斷喚醒
- WFE指令進入睡眠模式,可被喚醒事件喚醒
WFI 模式實現代碼
#include "stm32f10x.h"
// 初始化NVIC中斷(用於WFI喚醒)
void NVIC_Init_For_WFI(void) {
NVIC_InitTypeDef NVIC_InitStructure;
// 配置某中斷(如外部中斷EXTI0)
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 配置睡眠模式(SLEEP-ON-EXIT使能)
void Sleep_Mode_Config(void) {
// 使能SLEEPONEXIT位:執行完中斷服務程序後進入睡眠
SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
// 選擇睡眠模式為“深度睡眠禁用”(即普通睡眠模式)
PWR->CR &= ~PWR_CR_PDDS;
PWR->CR |= PWR_CR_CWUF; // 清除喚醒標誌
}
int main(void) {
// 系統初始化(時鐘、外設等)
SystemInit();
NVIC_Init_For_WFI();
Sleep_Mode_Config();
while(1) {
// 執行WFI指令進入睡眠,被任意NVIC中斷喚醒後繼續執行
__WFI();
// 喚醒後從這裏繼續運行
}
}
// 中斷服務程序(示例:EXTI0中斷)
void EXTI0_IRQHandler(void) {
if(EXTI_GetITStatus(EXTI_Line0) != RESET) {
// 中斷處理邏輯
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
2.2 停止模式
- 執行完WFI/WFE指令後,STM32進入停止模式,程序暫停運行,喚醒後程序從暫停的地方繼續運行
- 1.8V供電區域的所有時鐘都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器內容被保留下來
- 在停止模式下,所有的I/O引腳都保持它們在運行模式時的狀態
- 當一箇中斷或喚醒事件導致退出停止模式時,HSI被選為系統時鐘
- 當電壓調節器處於低功耗模式下,系統從停止模式退出時,會有一段額外的啓動延時
- WFI指令進入停止模式,可被任意一個EXTI中斷喚醒
- WFE指令進入停止模式,可被任意一個EXTI事件喚醒
停止模式(WFI 喚醒,EXTI 中斷觸發)
#include "stm32f10x.h"
// 初始化EXTI中斷(用於喚醒停止模式)
void EXTI_Init_For_Stop(void) {
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能GPIO和AFIO時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
// 配置GPIO為輸入模式(如GPIOA0)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置EXTI中斷
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 上升沿觸發中斷
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
// 配置NVIC中斷
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// 停止模式配置
void Stop_Mode_Config(void) {
// 使能深度睡眠
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
// 選擇停止模式(PDDS=0,LPDS=1)
PWR->CR |= PWR_CR_LPDS;
PWR->CR &= ~PWR_CR_PDDS;
PWR->CR |= PWR_CR_CWUF; // 清除喚醒標誌
}
int main(void) {
// 系統初始化(時鐘、外設等)
SystemInit();
EXTI_Init_For_Stop();
Stop_Mode_Config();
while(1) {
// 執行WFI指令進入停止模式,被EXTI0中斷喚醒後繼續執行
__WFI();
// 喚醒後從這裏繼續運行
}
}
// EXTI0中斷服務程序
void EXTI0_IRQHandler(void) {
if(EXTI_GetITStatus(EXTI_Line0) != RESET) {
// 中斷處理邏輯
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
2.3 待機模式
- 執行完WFI/WFE指令後,STM32進入待機模式,喚醒後程序從頭開始運行
- 整個1.8V供電區域被斷電,PLL、HSI和HSE也被斷電,SRAM和寄存器內容丟失,只有備份的寄存器和待機電路維持供電
- 在待機模式下,所有的I/O引腳變為高阻態(浮空輸入)
- WKUP引腳的上升沿、RTC鬧鐘事件的上升沿、NRST引腳上外部復位、IWDG復位退出待機模式
待機模式WKUP引腳 實現代碼
#include "stm32f10x.h"
void Standby_Mode_Config(void) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
PWR->CR |= PWR_CR_PDDS; // 選擇待機模式
PWR_WakeUpPinCmd(ENABLE); // 使能WKUP引腳喚醒
PWR->CR |= PWR_CR_CWUF; // 清除喚醒標誌
__WFI(); // 進入待機模式
}
int main(void) {
SystemInit();
Standby_Mode_Config();
// 喚醒後從頭執行,需重新初始化
while(1) {
// 應用邏輯
}
}