stm32之电源管理(实现低功耗)
目錄
1.硬件原理
2.低功耗模式
3.睡眠模式實驗
4.停止模式實驗
5.待機模式實驗
前言:STM32F10xxx系列產品都有電源管理模塊,芯片功耗會影響到一個產品的續航能力;比如在一些終端傳感器場合里,為了減輕后期的維護投入,要求長期工作時間較長,更需要合理的芯片功耗管理。芯片自帶幾種運行模式,包括正常模式、睡眠模式、停止模式、待機模式。越往后,芯片的功耗越低,但能執行功能就越少。低功耗的電源管理策略就是在芯片不需要對外界響應的時候進入低功耗模式,而當外界條件滿足的時候,退出低功耗模式(喚醒),正常執行處理工作。下面對其模式之間的轉換和各個模式下的芯片內部的運轉情況等一探究竟。
寫代碼前要先了解芯片的特性及工作原理,難免會先閱讀一些長長的文檔。下面核心講解一些要點。
1.硬件原理
下圖是芯片的電源框架:
圖左邊7個電壓點對應芯片的7個引腳,在芯片電路原理圖能找到對應的引腳。
、:是ADC轉換器的參考電壓,有些芯片沒有這連個引腳,內部已經把他們接到、了。
、:是ADC轉換器的供電電源,獨立電源供電是為了過濾和屏蔽來自印刷電路板上的毛刺干擾,提高轉換的精確度。(也可以直接連到、)。
、:STM32的工作電壓(VDD)為2.0~3.6V。通過內置的電壓調節器提供所需的1.8V電源。
:使用電池或其他電源連接到VBAT腳上,當VDD斷電時,可以保存備份寄存器的內容和維持RTC的
功能。(如果沒有外部電池,好像不接也可以,但是數據手冊說必須接到)。
電池備份區域:
當備份區域由VDD(內部模擬開關連到VDD)供電時,下述功能可用:
??? ● PC14和PC15可以用于GPIO或LSE(低速外部時鐘)引腳
??? ● PC13可以作為通用I/O口、TAMPER引腳、RTC校準時鐘、RTC鬧鐘或秒輸出
當后備區域由VBAT供電時(VDD消失后模擬開關連到VBAT),可以使用下述功能:
??? ● PC14和PC15只能用于LSE(低速外部時鐘)引腳
??? ● PC13可以作為TAMPER引腳、RTC鬧鐘或秒輸出
電壓調節器:
復位后調節器總是使能的。根據應用方式它以3種不同的模式工作。
???? ● 運轉模式:調節器以正常功耗模式提供1.8V電源(內核,內存和外設)。
???? ● 停止模式:調節器以低功耗模式提供1.8V電源,以保存寄存器和SRAM的內容。
???? ● 待機模式:調節器停止供電。除了備用電路和備份域外,寄存器和SRAM的內容全部丟失。
2.低功耗模式
STM32F10xxx有三種低功耗模式:
???? ● 睡眠模式(Cortex?-M3內核停止,所有外設包括Cortex-M3核心的外設,如NVIC、系統時鐘(SysTick)等仍在運行)
???? ● 停止模式(所有的時鐘都已停止)
???? ● 待機模式(1.8V電源關閉)
此外,在運行模式下,可以通過以下方式中的一種降低功耗:
● 降低系統時鐘
● 關閉APB和AHB總線上未被使用的外設時鐘。
注意:在睡眠模式、停止模式及待機模式中,若備份區域電源正常供電,備份區域的RTC都可以正常運行、備份區域內的寄存器及備份區域內的SRAM數據會被保存,不受功耗模式影響。
3.睡眠模式實驗
下面代碼利用編譯器內置函數__WFI()進入睡眠,任何中斷將退出睡眠(實驗使用串口中斷和外部中斷)。利用串口將芯片狀態信息發送出來。可以先把代碼復制到工程編譯下載,實驗現象通過串口上位機觀察,如果有可調電源的話,可以對比正常工作和睡眠模式下的電流大小,正常來說睡眠模式下功率低,那么電流會比正常工作下低。下面程序并不復雜,程序進入while循環延時一段時間就會進入睡眠狀態,利用上位機向串口發送數據或者將PA.0引腳接電源都可產生中斷,從而退出睡眠模式。
#include "stm32f10x.h" #include "stdio.h"static void EXTI_Key_Config(void); static void NVIC_Configuration(void); static void USART1_Config(void); static void Delay(__IO u32 nCount);int main(void) { USART1_Config();EXTI_Key_Config();//配置中斷控制器NVICNVIC_Configuration();while(1){printf("STM32正常運行.\r\n");Delay(0xfffff);//NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,DISABLE);//調用__WFI時立即進入睡眠NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,ENABLE);//調用__WFI時,等待系統從最低優先級的中斷處理程序中退出后進入睡眠printf("STM32進入睡眠.\r\n");__WFI();//WFI指令進入睡眠//開始等待中斷喚醒Delay(0xfffff);printf("已退出睡眠模式.\r\n");} }static void EXTI_Key_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;//開啟外設時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);//初始化 GPIOA.0 設置為下拉輸入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOA, &GPIO_InitStructure);//GPIOA.0 中斷線配置GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//GPIOA.0 中斷初始化配置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寄存器EXTI_Init(&EXTI_InitStructure); }void USART1_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;//配置串口1(USART1)時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);//配置串口1(USART1 Tx (PA.09))GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//配置串口1 USART1 Rx (PA.10)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);//串口1模式(USART1 mode)配置 USART_InitStructure.USART_BaudRate = 9600;//一般設置為9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No ;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟中斷USART_Cmd(USART1, ENABLE); //使能串口 }int fputc(int ch, FILE *f)//重寫標準庫的fputc函數 {//將Printf內容發往串口USART_SendData(USART1, (unsigned char) ch);while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET); return (ch); }static void NVIC_Configuration(void) {NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);//使能外部中斷 PA.0NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_Init(&NVIC_InitStructure);//使能串口1中斷 }void Delay(__IO u32 nCount) //簡單的延時函數 {for(; nCount != 0; nCount--); }在stm32f10x_it.c文件加入:
#include "delay.h" void EXTI0_IRQHandler(void) { Delay(0xFFFFF);//防抖//檢查指定的EXTI0線路觸發請求發生與否if(EXTI_GetITStatus(EXTI_Line0) != RESET) { printf("按鍵中斷喚醒.\r\n");}//清除EXTI0線路掛起位EXTI_ClearITPendingBit(EXTI_Line0); }void USART1_IRQHandler(void) {unsigned char code;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ code=USART_ReceiveData(USART1);printf("串口中斷喚醒.\r\n");} }| 立即睡眠 | 在執行__WFI或__WFE指令時立即進入睡眠模式 |
| 退出時睡眠 | 在退出優先級最低的中斷服務程序后才進入睡眠模式 |
| 進入方式 | 內核寄存器SLEEPDEEP=0,然后調用WFI或者WFE指令即可進入睡眠模式 另外若內核寄存器SLEEPONEXIT=0,進入“立即睡眠”模式;SLEEPONEXIT=1,進入“退出時睡眠” |
| 喚醒方式 | 如果是使用WFI指令睡眠,則可使用任意中斷喚醒 如果是使用WFE指令睡眠,則由事件喚醒 |
| 睡眠時 | 關閉內核時鐘,內核停止,而外設正常運行,在軟件上表現為不再執行新的代碼。這個狀態會保留睡眠前的內核寄存器、內存數據(RAM數據),所有的I/O引腳都保持它們在運行模式時的狀態 |
| 喚醒延時 | 無延時 |
| 喚醒后 | 若有中斷喚醒,先進入中斷,退出中斷服務程序后,接著執行WFI指令后的程序;若由事件喚醒,直接執行WFE后的程序 |
注意:在系統處于睡眠低功耗模式(包括后面介紹的停止模式、待機模式)時,不能用下載器進行程序下載,所以下載程序時要先把系統喚醒?;蛘呤褂萌缦路椒?#xff1a;按著板子的復位鍵,點擊電腦端的“下載”,然后松開復位鍵,就能正常給板子下載程序了。
4.停止模式實驗
停止模式是在Cortex?-M3的深睡眠模式基礎上結合了外設的時鐘控制機制,在停止模式下電壓調節器可運行在正常或低功耗模式。此時在1.8V供電區域的的所有時鐘都被停止,PLL、HSI和HSE RC振蕩器的功能被禁止,SRAM和寄存器內容被保留下來。
停止模式的功耗比睡眠模式更低,代碼操作上相對比睡眠模式復雜一點。跟睡眠模式的喚醒不同,只有EXTI線的中斷才能退出停止模式,因為其他外設在停止模式時被關閉,并不能響應中斷。將mani函數替換為下面代碼,其他不變:
int main(void) { USART1_Config();EXTI_Key_Config();NVIC_Configuration();//配置中斷控制器NVICRCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能電源管理單元的時鐘while(1){printf("STM32正常運行.\r\n");Delay(0xfffff);printf("STM32進入停止模式.\r\n");PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);//進入停止模式,設置電壓調節器為低功耗模式,等待中斷喚醒//PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);//進入停止模式,設置電壓調節器為正常模式,等待中斷喚醒//開始等待任意EXTI線中斷喚醒SystemInit();//喚醒后需要恢復系統時鐘,因為退出停止模式后,系統默認使用的HSI作為系統時鐘/*實際上在運行main函數前,會先執行SystemInit函數以配置系統時鐘,這個在啟動文件里可以看到。*///剛退出停止模式時,使用HSI作為系統時鐘,回影響串口波特率//輸出不對,在重新配置時鐘后才能使用串口的輸出Delay(0xfffff);printf("已退出停止模式.\r\n");} }| 調壓器低功耗模式 | 調壓器可工作在正常模式或低功耗模式,可進一步降低功耗 |
| 進入方式 | 內核寄存器SLEEPDEEP=1,PWR_CR寄存器的PDDS=0,然后調用WFI或者WFE指令即可進入睡眠模式 PWR_CR寄存器的LPDS=0時,調壓器工作在正常模式,LPDS=1時工作在低功耗模式 除了通過配置寄存器,還可以直接調用標準庫函數PWR_EnterSTOPMode,如上代碼 |
| 喚醒方式 | 如果是WFI指令進入停止模式的,可使用任意EXTI線的中斷喚醒 如果是WFE指令進入停止模式的,可使用任意配置為事件模式的EXTI線事件喚醒 |
| 停止時 | 內核停止,外設也停止。這個狀態會保留停止前的內核寄存器、內存的數據(RAM) |
| 喚醒方式 | 基礎延時是HSI振蕩器的啟動時間,若調壓器工作在低功耗模式,還需要加上調壓器從低功耗模式切換至正常模式下的時間 |
| 喚醒后 | 若有中斷喚醒,先進入中斷,退出中斷服務程序后,接著執行WFI指令后的程序;若由事件喚醒,直接執行WFE后的程序。喚醒后,STM32會使用HSI作為系統時鐘 |
5.待機模式實驗
待機模式可實現系統的最低功耗。該模式是在Cortex-M3深睡眠模式時關閉電壓調節器。整個1.8V供電區域被斷電。PLL、HSI和HSE振蕩器也被斷電。SRAM和寄存器內容丟失。只有備份的寄存器和待機電路維持供電。也就是說從待機模式喚醒后,由于沒有之前代碼的運行記錄,只能對芯片復位,重新檢測boot條件,從頭開始執行程序。它有4種喚醒方式,分別是WAUP(PA0)引腳的上升沿、RTC鬧鐘事件、NRST引腳的復位和IWDG(獨立看門狗)復位。
我們不需要對PA.0引腳進行如上面的初始化,也不需要初始化一個外部中斷,將下面兩個函數替換,其余保持不變:
int main(void) { USART1_Config();//EXTI_Key_Config();//配置中斷控制器NVICNVIC_Configuration();RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能電源管理單元的時鐘if(PWR_GetFlagStatus(PWR_FLAG_WU)){printf("\r\n待機模式復位.\r\n");}else{printf("\r\n非待機模式復位.\r\n");}while(1){printf("STM32正常運行.\r\n");Delay(0xfffff);printf("STM32進入待機模式.\r\n");PWR_ClearFlag(PWR_FLAG_WU);//清除喚醒標志狀態PWR_WakeUpPinCmd(ENABLE);//使能Wake引腳的喚醒功能,使能PA0PWR_EnterSTANDBYMode();//進入待機模式} }static void NVIC_Configuration(void) {NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //NVIC_Init(&NVIC_InitStructure);//使能外部中斷 PA.0NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_Init(&NVIC_InitStructure);//使能串口1中斷 }程序下載后,按下復位鍵,串口會打印非待機模式復位,接著運行while函數,延時后進入待機模式,等待喚醒,在PA0引腳給上升沿信號,串口打印已待機模式復位,代碼重頭開始執行。
| 進入方式 | 內核寄存器SLEEPDEEP=1,PWR_CR寄存器中的PDDS=1,PWR_CR寄存器中的喚醒狀態為WUF=0,然后調用WFI或者調用WFE指令即可進入待機模式(沒區別) |
| 喚醒方式 | 通過WAUP引腳的上升沿,RTC鬧鐘、喚醒、入侵、時間戳事件或NRST引腳外部復位及IWDG復位喚醒 |
| 待機時 | 內核停止,片上外設也停止;內核寄存器、內存的數據會丟失;除了復位引腳、RTC_AF1引腳及WAUP引腳外,其他I/O口均工作在高阻態 |
| 喚醒延遲 | 芯片復位時間 |
| 喚醒后 | 相當于芯片復位,在程序表現為從頭開始執行代碼(等于重新上電) |
最后,除了利用上面三種模式實現低功耗外,還可以在運行模式下,關閉某些外設時鐘或者利用分頻器降低外設時鐘,同樣也可以減低系統功耗。電池備份區域部分這里沒有細說,后面單獨一篇介紹。
?
?
道雖邇,不行不至,事雖小,不為不成。——《荀子》
總結
以上是生活随笔為你收集整理的stm32之电源管理(实现低功耗)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于stm32、0.96寸OLED实现的
- 下一篇: stm32之PVD可编程电压监测器(掉电