一、電源框圖
電壓調節器是 STM32 的電源系統中最核心部分,連接 VDD 供電區域和 1.8 供電區域。
二、電源管理

立即睡眠 | 在執行?WFI?或?WFE?指令時立即進入睡眠模式。 |
退出時睡眠 | 在退出優先級最低的中斷服務程序后才進入睡眠模式。 |
進入方式 | 內核寄存器的SLEEPDEEP?=?0?,然后調用WFI或WFE指令即可進入睡眠模式; 另外若內核寄存器的SLEEPONEXIT=0時,進入“立即睡眠”模式,SLEEPONEXIT=1時,進入“退出時睡眠”模式。 |
喚醒方式 | 如果是使用WFI指令睡眠的,則可使用任意中斷喚醒; 如果是使用WFE指令睡眠的,則由事件喚醒。 |
睡眠時 | 關閉內核時鐘,內核停止,而外設正常運行,在軟件上表現為不再執行新的代碼。這個狀態會保留睡眠前的內核寄存器、內存的數據。 |
喚醒延遲 | 無延遲。 |
喚醒后 | 若由中斷喚醒,先進入中斷,退出中斷服務程序后,接著執行WFI指令后的程序;若由事件喚醒,直接接著執行WFE后的程序。 |
只需要調用這個函數,選擇一下進入模式,中斷進入/時間進入。PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instructionPWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instructionHAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
2.2、停止模式
調壓器低功耗模式 | 在停止模式下調壓器可工作在正常模式或低功耗模式,可進一步降低功耗 |
FLASH掉電模式 | 在停止模式下FLASH可工作在正常模式或掉電模式,可進一步降低功耗 |
進入方式 | 內核寄存器的SLEEPDEEP?=1,PWR_CR寄存器中的PDDS=0,然后調用WFI或WFE指令即可進入停止模式; PWR_CR?寄存器的LPDS=0時,調壓器工作在正常模式,LPDS=1時工作在低功耗模式; |
喚醒方式 | 如果是使用WFI指令睡眠的,可使用任意EXTI線的中斷喚醒; 如果是使用WFE指令睡眠的,可使用任意配置為事件模式的EXTI線事件喚醒。 |
停止時 | 內核停止,片上外設也停止。這個狀態會保留停止前的內核寄存器、內存的數據。 |
喚醒延遲 | 基礎延遲為HSI振蕩器的啟動時間,若調壓器工作在低功耗模式,還需要加上調壓器從低功耗切換至正常模式下的時間,若FLASH工作在掉電模式,還需要加上FLASH從掉電模式喚醒的時間。 |
用KEY0來進入停止模式,然后使用任意外部中斷喚醒。uint8_t KEY0_Scan(void) {static uint8_t key_pressed = 0; if (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_RESET) {HAL_Delay(20); if (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_RESET && key_pressed == 0) {key_pressed = 1; while (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_RESET);printf("按鍵0觸發了,進入停止模式\n"); I2C_Write(0,I2C_Wbuf, strlen((char*)I2C_Wbuf) + 1);HAL_PWR_EnterSTOPMode(1, PWR_SLEEPENTRY_WFI);return 1; }} else {key_pressed = 0;}return 0;}退出停止模式
因為停止模式,會關閉HSE和PLL,所以在退出時,必須重新開啟HSE和PLL。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作為系統時鐘__HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_PLLCLK);while(__HAL_RCC_GET_SYSCLK_SOURCE() != 0x08 ){}
}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if (GPIO_Pin == GPIO_PIN_2) {CLK_Resume();printf("退出停止模式\n");key_pressed_flag = 1; key_debounce_start = HAL_GetTick(); __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_2); }
}
現象:

進入方式 | 內核寄存器的SLEEPDEEP?=1,PWR_CR寄存器中的PDDS=1,PWR_CR寄存器中 |
喚醒方式 | 通過WKUP引腳的上升沿,RTC鬧鐘、喚醒、入侵、時間戳事件或NRST引腳外部復位 |
待機時 | 內核停止,片上外設也停止;內核寄存器、內存的數據會丟失;除復位引腳、 |
喚醒延遲 | 芯片復位的時間 |
喚醒后 | 相當于芯片復位,在程序表現為從頭開始執行代碼。 |
//下述代碼實現了,按鍵1進入待機模式,并且用中斷0進行喚醒,喚醒后相當于重新上電。
uint8_t key_pressed_flag = 0;
uint32_t key_debounce_start = 0; void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //將PA0配置為中斷模式
{if(GPIO_Pin == GPIO_PIN_0){HAL_ResumeTick(); //恢復systick中斷,否則不能使用HAL_Delayprintf("退出待機模式\n");key_pressed_flag = 1; key_debounce_start = HAL_GetTick(); __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0); }
}void KEYUP_Scan(void)
{
if (key_pressed_flag == 1) {if (HAL_GetTick() - key_debounce_start > 20) {if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) {if (HAL_GetTick() - key_debounce_start > 1000) {break; }} printf("按鍵2觸發!LED狀態已翻轉\n"); }key_pressed_flag = 0; }
}
}
uint8_t KEY1_Scan(void) {static uint8_t key_pressed = 0; if (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == GPIO_PIN_RESET) {HAL_Delay(20); if (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == GPIO_PIN_RESET && key_pressed == 0) {key_pressed = 1; while (HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_3) == GPIO_PIN_RESET);printf("按鍵1觸發了,進入待機模式\n"); HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); //使能喚醒引腳__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);HAL_PWR_EnterSTANDBYMode(); //進入到待機模式return 1; }} else { key_pressed = 0;}return 0;
}void Key_Process(void)
{KEY1_Scan();KEYUP_Scan();
}