阿米納網(wǎng)站建設(shè)網(wǎng)上互聯(lián)網(wǎng)推廣
注: 本文是學習野火的指南針開發(fā)板過程的學習筆記,可能有誤,詳細請看B站野火官方配套視頻教程(這個教程真的講的很詳細,請給官方三連吧)
在響應(yīng)綠色發(fā)展的同時,在很多應(yīng)用場合中都對電子設(shè)備的功耗要求非??量?#xff0c;如某些傳感器信息采集設(shè)備,僅靠小型的電池提供電源,要求工作長達數(shù)年之久,且期間不需要任何維護;由于智慧穿戴設(shè)備的小型化要求,電池體積不能太大導(dǎo)致容量也比較小,所以也很有必要從控制功耗入手,提高設(shè)備的續(xù)行時間。
?01 STM32的電源管理簡介
STM32有專門的電源管理外設(shè)監(jiān)控電源并管理設(shè)備的運行模式,確保系統(tǒng)正常運行,并盡量降低器件的功耗。
電源監(jiān)控器:
STM32芯片主要通過引腳VDD從外部獲取電源,在它的內(nèi)部具有電源監(jiān)控器用于檢測VDD的電壓,以實現(xiàn)復(fù)位功能及掉電緊急處理功能,保證系統(tǒng)可靠地運行。
1. 上電復(fù)位與掉電復(fù)位(POR與PDR)
POR、PDR功能是使用其電壓閾值與外部供電電壓VDD比較,當?shù)陀诠ぷ鏖撝禃r,會直接進入復(fù)位狀態(tài),這可防止電壓不足導(dǎo)致的誤操作
當檢測到VDD的電壓低于閾值VPOR及VPDR時(無需外部電路輔助)STM32芯片會自動保持在復(fù)位狀態(tài),防止因電壓不足強行工作而帶來嚴重的后果。在剛開始電壓低于VPOR時(約1.92V),STM32保持在上電復(fù)位狀態(tài)(POR,Power On Reset),當VDD電壓持續(xù)上升至大于VPOR時,芯片開始正常運行,而在芯片正常運行的時候,當檢測到VDD電壓下降至低于VPDR閾值(約1.88V),會進入掉電復(fù)位狀態(tài)(PDR,Power Down Reset)。
2.可編程電壓檢測器PVD
STM32還提供了可編程電壓檢測器PVD,它也是實時檢測VDD的電壓
當檢測到電壓低于編程的VPVD閾值時,會向內(nèi)核產(chǎn)生一個PVD中斷(EXTI16線中斷)以使內(nèi)核在復(fù)位前進行緊急處理。該電壓閾值可通過電源控制寄存器PWR_CSR設(shè)置。
使用PVD可配置8個等級,如下表。其中的上升沿和下降沿分別表示類似前面圖中的VDD電壓上升過程及下降過程的閾值:
閾值等級 | 條件 | 最小值 | 典型值 | 最大值 | 單位 |
級別0 | 上升沿 | 2.1 | 2.18 | 2.26 | V |
下降沿 | 2 | 2.08 | 2.16 | V | |
級別1 | 上升沿 | 2.19 | 2.28 | 2.37 | V |
下降沿 | 2.09 | 2.18 | 2.27 | V | |
級別2 | 上升沿 | 2.28 | 2.38 | 2.48 | V |
下降沿 | 2.18 | 2.28 | 2.38 | V | |
級別3 | 上升沿 | 2.38 | 2.48 | 2.58 | V |
下降沿 | 2.28 | 2.38 | 2.48 | V | |
級別4 | 上升沿 | 2.47 | 2.58 | 2.69 | V |
下降沿 | 2.37 | 2.48 | 2.59 | V | |
級別5 | 上升沿 | 2.57 | 2.68 | 2.79 | V |
下降沿 | 2.47 | 2.58 | 2.69 | V | |
級別6 | 上升沿 | 2.66 | 2.78 | 2.9 | V |
下降沿 | 2.56 | 2.68 | 2.8 | V | |
級別7 | 上升沿 | 2.76 | 2.88 | 3 | V |
下降沿 | 2.66 | 2.78 | 2.9 | V |
?STM32的電源系統(tǒng):
為了方便進行電源管理,STM32把它的外設(shè)、內(nèi)核等模塊跟據(jù)功能劃分了供電區(qū)域,其內(nèi)部電源區(qū)域劃分如圖:
??STM32的電源系統(tǒng)主要分為備份域電路、內(nèi)核電路以及ADC電路三部分,介紹如下:
- ADC電源及參考電壓(VDDA供電區(qū)域):
為了提高轉(zhuǎn)換精度,STM32的ADC配有獨立的電源接口,方便進行單獨的濾波。ADC的工作電源使用VDDA引腳輸入,使用VSSA作為獨立的地連接,VREF引腳則為ADC提供測量使用的參考電壓。 - 調(diào)壓器供電電路( V DD /1.8V 供電區(qū)域):在 STM32 的電源系統(tǒng)中調(diào)壓器供電的電路是最主要的部分,調(diào)壓器為備份域及待機電路的所有數(shù)字電路供電,其中包括內(nèi)核、數(shù)字外設(shè)以及 RAM ,調(diào)壓器的輸出電壓約為 1.8V ,因而使用調(diào)壓器供電的這些電路區(qū)域被稱為 1.8V 域。
調(diào)壓器可以運行在“運行模式”、“停止模式”以及“待機模式”。在運行模式下,1.8域全功率運行;在停止模式下 1.8V 域運行在低功耗狀態(tài),1.8V 區(qū)域的所有時鐘都關(guān)閉,相應(yīng)的外設(shè)都停止了工作,但它會保留內(nèi)核寄存器以及 SRAM 的內(nèi)容;在機模式下,整個 1.8V 域都斷電,該區(qū)域的內(nèi)核寄存器及 SRAM 內(nèi)容都會丟失 (備區(qū)域的寄存器不受影響)。
- 備份域電路(后備供電區(qū)域):? ? ?
STM32的LSE振蕩器、RTC及備份寄存器這些器件被包含進備份域電路中,這部分的電路可以通過STM32的VBAT引腳獲取供電電源,在實際應(yīng)用中一般會使用3V的鈕扣電池對該引腳供電。
?在圖中后備供電區(qū)域的左側(cè)有一個電源開關(guān)結(jié)構(gòu),它的功能類似下圖的雙二極管,在它的“1”處連接了VBAT電源,“2”處連接了VDD主電源(一般為3.3V),右側(cè)“3”處引出到備份域電路中。當VDD主電源存在時,由于VDD電壓較高,備份域電路通過VDD供電,節(jié)省鈕扣電池的電源,僅當VDD掉電時,備份域電路由鈕扣電池通過VBAT供電,保證電路能持續(xù)運行,從而可利用它保留關(guān)鍵數(shù)據(jù)。
02 STM32的功耗模式?
按功耗由高到低排列,STM32具有運行、睡眠、停止和待機四種工作模式。上電復(fù)位后STM32處于運行狀態(tài)時,當內(nèi)核不需要繼續(xù)運行,就可以選擇進入后面的三種低功耗模式降低功耗,這三種模式中,電源消耗不同、喚醒時間不同、喚醒源不同,用戶需要根據(jù)應(yīng)用需求,選擇最佳的低功耗模式。
這三種低功耗模式層層遞進,運行的時鐘或芯片功能越來越少,因而功耗越來越低。
?1.睡眠模式
在睡眠模式中,僅關(guān)閉了內(nèi)核時鐘,內(nèi)核停止運行,但其片上外設(shè),CM3核心的外設(shè)全都還照常運行。 ?? ?有兩種方式進入睡眠模式,它的進入方式?jīng)Q定了從睡眠喚醒的方式,分別是WFI(wait for interrupt)和WFE(wait for event),即由等待“中斷”喚醒和由“事件”喚醒。睡眠模式的各種特性見下表:
2.停止模式?
在停止模式中,進一步關(guān)閉了其它所有的時鐘,于是所有的外設(shè)都停止了工作,但由于其1.8V區(qū)域的部分電源沒有關(guān)閉,還保留了內(nèi)核的寄存器、內(nèi)存的信息,所以從停止模式喚醒,并重新開啟時鐘后,還可以從上次停止處繼續(xù)執(zhí)行代碼。停止模式可以由任意一個外部中斷(EXTI)喚醒,在停止模式中可以選擇電壓調(diào)節(jié)器為開模式或低功耗模式。停止模式的各種特性見下表:
3.待機模式
?待機模式,它除了關(guān)閉所有的時鐘,還把1.8V區(qū)域的電源也完全關(guān)閉了,也就是說,從待機模式喚醒后,由于沒有之前代碼的運行記錄,只能對芯片復(fù)位,重新檢測boot條件,從頭開始執(zhí)行程序。它有四種喚醒方式,分別是WKUP(PA0)引腳的上升沿,RTC鬧鐘事件,NRST引腳的復(fù)位和IWDG(獨立看門狗)復(fù)位。
在以上講解的睡眠模式、停止模式及待機模式中,若備份域電源正常供電,備份域內(nèi)的RTC都可以正常運行,備份域內(nèi)的寄存器的數(shù)據(jù)會被保存,不受功耗模式影響。?
03電源管理相關(guān)的庫函數(shù)及命令
STM32標準庫對電源管理提供了完善的函數(shù)及命令,使用它們可以方便地進行控制。
配置PVD監(jiān)控功能
PVD可監(jiān)控VDD的電壓,當它低于閾值時可產(chǎn)生PVD中斷以讓系統(tǒng)進行緊急處理,這個閾值可以直接使用庫函數(shù)PWR_PVDLevelConfig配置成前面閾值表中說明的閾值等級。
進入睡眠——WFI與WFE命令
在前面可了解到進入各種低功耗模式時都需要調(diào)用WFI或WFE命令,它們實質(zhì)上都是內(nèi)核指令,在庫文件core_cm3.h中把這些指令封裝成了函數(shù):
對于這兩個指令,應(yīng)用時只需要知道,調(diào)用它們都能進入低功耗模式,需要使用函數(shù)的格式“__WFI();”和“__WFE();”來調(diào)用(因為__wfi及__wfe是編譯器內(nèi)置的函數(shù),函數(shù)內(nèi)部使用調(diào)用了相應(yīng)的匯編指令)。
進入停止模式
直接調(diào)用WFI和WFE指令可以進入睡眠模式,而進入停止模式則還需要在調(diào)用指令前設(shè)置一些寄存器位,STM32標準庫把這部分的操作封裝到PWR_EnterSTOPMode函數(shù)中了,它的定義如下:
1 /**
2 * @brief 進入停止模式
3 *
4 * @note 在停止模式下所有 I/O 的會保持在停止前的狀態(tài)
5 * @note 從停止模式喚醒后,會使用 HSI 作為時鐘源
6 * @note 調(diào)壓器若工作在低功耗模式,可減少功耗,但喚醒時會增加延遲
7 * @param PWR_Regulator: 設(shè)置停止模式時調(diào)壓器的工作模式
8 * @arg PWR_MainRegulator_ON: 調(diào)壓器正常運行
9 * @arg PWR_Regulator_LowPower: 調(diào)壓器低功耗運行
10 * @param PWR_STOPEntry: 設(shè)置使用 WFI 還是 WFE 進入停止模式
11 * @arg PWR_STOPEntry_WFI: WFI 進入停止模式
12 * @arg PWR_STOPEntry_WFE: WFE 進入停止模式13 * @retval None
14 */
15 void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
16 {
17 uint32_t tmpreg = 0;
18 /* 檢查參數(shù) */
19 assert_param(IS_PWR_REGULATOR(PWR_Regulator));
20 assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
21
22 /* 設(shè)置調(diào)壓器的模式 ------------*/
23 tmpreg = PWR->CR;
24 /* 清除 PDDS 及 LPDS 位 */
25 tmpreg &= CR_DS_MASK;
26 /* 根據(jù) PWR_Regulator 的值 (調(diào)壓器工作模式) 配置 LPDS,MRLVDS 及 LPLVDS 位 */
27 tmpreg |= PWR_Regulator;
28 /* 寫入?yún)?shù)值到寄存器 */
29 PWR->CR = tmpreg;
30 /* 設(shè)置內(nèi)核寄存器的 SLEEPDEEP 位 */
31 SCB->SCR |= SCB_SCR_SLEEPDEEP;
32
33 /* 設(shè)置進入停止模式的方式-----------------*/
34 if (PWR_STOPEntry == PWR_STOPEntry_WFI) {
35 /* 需要中斷喚醒 */
36 __WFI();
37 } else {
38 /* 需要事件喚醒 */
39 __WFE();
40 }
41
42 /* 以下的程序是當重新喚醒時才執(zhí)行的,清除 SLEEPDEEP 位的狀態(tài) */
43 SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
44 }
????????這個函數(shù)有兩個輸入?yún)?shù),分別用于控制調(diào)壓器的模式及選擇使用WFI或WFE停止,代碼中先是根據(jù)調(diào)壓器的模式配置PWR_CR寄存器,再把內(nèi)核寄存器的SLEEPDEEP位置1,這樣再調(diào)用WFI或WFE命令時,STM32就不是睡眠,而是進入停止模式了。函數(shù)結(jié)尾處的語句用于復(fù)位SLEEPDEEP位的狀態(tài),由于它是在WFI及WFE指令之后的,所以這部分代碼是在STM32被喚醒的時候才會執(zhí)行。 ?? ?
????????要注意的是進入停止模式后,STM32的所有I/O都保持在停止前的狀態(tài),而當它被喚醒時,STM32使用HSI作為系統(tǒng)時鐘(8MHz)運行,由于系統(tǒng)時鐘會影響很多外設(shè)的工作狀態(tài),所以一般我們在喚醒后會重新開啟HSE,把系統(tǒng)時鐘設(shè)置回原來的狀態(tài)。
進入待機模式
STM32標準庫也提供了控制進入待機模式的函數(shù),其定義如下:
1 /**
2 * @brief 進入待機模式
3 * @note 待機模式時,除以下引腳,其余引腳都在高阻態(tài):
4 * -復(fù)位引腳
5 * - RTC_AF1 引腳 (PC13) (需要使能侵入檢測、時間戳事件或 RTC 鬧鐘事件)
6 * - RTC_AF2 引腳 (PI8) (需要使能侵入檢測或時間戳事件)
7 * - WKUP 引腳 (PA0) (需要使能 WKUP 喚醒功能)
8 * @note 在調(diào)用本函數(shù)前還需要清除 WUF 寄存器位
9 * @param None
10 * @retval None
11 */
12 void PWR_EnterSTANDBYMode(void)
13 {
14 /* 清除 Wake-up 標志 */
15 PWR->CR |= PWR_CR_CWUF;
16 /* 選擇待機模式 */
17 PWR->CR |= PWR_CR_PDDS;
18 /* 設(shè)置內(nèi)核寄存器的 SLEEPDEEP 位 */
19 SCB->SCR |= SCB_SCR_SLEEPDEEP;
20 /* 存儲操作完畢時才能進入待機模式,使用以下語句確保存儲操作執(zhí)行完畢 */
21 #if defined ( __CC_ARM )
22 __force_stores();
23 #endif
24 /* 等待中斷喚醒 */
25 __WFI();
26 }
該函數(shù)中先配置了PDDS寄存器位及SLEEPDEEP寄存器位,接著調(diào)用__force_stores函數(shù)確保存儲操作完畢后再調(diào)用WFI指令,從而進入待機模式。這里值得注意的是,待機模式也可以使用WFE指令進入的,如果您有需要可以自行修改。 ?? ?在進入待機模式后,除了被使能了的用于喚醒的I/O,其余I/O都進入高阻態(tài),而從待機模式喚醒后,相當于復(fù)位STM32芯片,程序重新從頭開始執(zhí)行。
?04電源管理實驗
PWR—睡眠模式(如何控制 STM32 進入低功耗睡眠模式。)
程序設(shè)計:
int main()
{(1) 初始化用于喚醒的中斷按鍵;
……………………………………………………………………
while(1){ /*********執(zhí)行任務(wù)***************************/printf("\r\n STM32正常運行,亮綠燈\r\n");LED_GREEN; Delay(0x3FFFFF);
(2) 進入睡眠狀態(tài);/*****任務(wù)執(zhí)行完畢,進入睡眠降低功耗***********/printf("\r\n 進入睡眠模式,按KEY1或KEY2按鍵可喚醒\r\n");//使用紅燈指示,進入睡眠狀態(tài)LED_RED;//進入睡眠模式__WFI(); //WFI指令進入睡眠(3) 使用按鍵中斷喚醒芯片;//由于 WFI 睡眠模式可以使用任意中斷喚醒,所以我們可以使用按鍵中斷喚醒。//等待中斷喚醒 K1或K2按鍵中斷 /***被喚醒,亮藍燈指示***/LED_BLUE; Delay(0x1FFFFF); printf("\r\n 已退出睡眠模式\r\n");//繼續(xù)執(zhí)行while循環(huán)}
}
/*按鍵中斷部分*/
void KEY1_IRQHandler(void)
{//確保是否產(chǎn)生了EXTI Line中斷if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {LED_BLUE; printf("\r\n KEY1 按鍵中斷喚醒 \r\n"); EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE); }
}void KEY2_IRQHandler(void)
{//確保是否產(chǎn)生了EXTI Line中斷if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {LED_BLUE;printf("\r\n KEY2 按鍵中斷喚醒 \r\n"); //清除中斷標志位EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE); }
}
注意 : 當系統(tǒng)處于睡眠模式低功耗狀態(tài)時 ( 包括后面講解的停止模式及待機模式 ) ,使用 DAP下載器是無法給芯片下載程序的,所以下載程序時要先把系統(tǒng)喚醒?;蛘呤褂萌缦路椒?#xff1a;按著板子的復(fù)位按鍵,使系統(tǒng)處于復(fù)位狀態(tài),然后點擊電腦端的下載按鈕下載程序,這時再釋放復(fù)位按鍵,就能正常給板子下載程序了。
PWR—停止模式實驗(解如何進入停止模式及喚醒后的狀態(tài)恢復(fù)。)
/*** @brief 停機喚醒后配置系統(tǒng)時鐘:
這個函數(shù)主要是調(diào)用了各種 RCC 相關(guān)的庫函數(shù),
開啟了 HSE 時鐘、使能 PLL 并且選擇 PLL 作
為時鐘源,從而恢復(fù)停止前的時鐘狀態(tài)。* @param None* @retval None*/
static void SYSCLKConfig_STOP(void)
{/* After wake-up from STOP reconfigure the system clock *//* 使能 HSE */RCC_HSEConfig(RCC_HSE_ON);/* 等待 HSE 準備就緒 */while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET){}/* 使能 PLL */ RCC_PLLCmd(ENABLE);/* 等待 PLL 準備就緒 */while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}/* 選擇PLL作為系統(tǒng)時鐘源 */RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);/* 等待PLL被選擇為系統(tǒng)時鐘源 */while (RCC_GetSYSCLKSource() != 0x08){}
}
main函數(shù)部分
/* 進入停止模式,設(shè)置電壓調(diào)節(jié)器為低功耗模式,等待中斷喚醒 */PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);
void KEY_IRQHandler(void)
{//確保是否產(chǎn)生了EXTI Line中斷if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {LED_BLUE;//由于停止喚醒后使用的是HSI時鐘,與原來使用的HSE時鐘時的頻率不一致,會影響波特率,若此處直接printf會亂碼//printf("\r\n KEY2 按鍵中斷喚醒 \r\n"); //清除中斷標志位EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE); }
}
為了更清晰地展示停止模式的影響,在剛喚醒后,我們定義了
RCC_ClocksTypeDef clock_status_wakeup,clock_status_config;uint8_t clock_source_wakeup,clock_source_config;
用于調(diào)用庫函數(shù) RCC_GetSYSCLKSourc以及 RCC_GetClocksFreq 獲取剛喚醒后的系統(tǒng)的時鐘源以及時鐘頻率,在使用 SYSCLKCon-fig_STOP 恢復(fù)時鐘后,我們再次獲取這些時狀態(tài),最后再通過串口打印出來。
//獲取剛被喚醒時的時鐘狀態(tài) //時鐘源clock_source_wakeup = RCC_GetSYSCLKSource ();//時鐘頻率RCC_GetClocksFreq(&clock_status_wakeup);//從停止模式下被喚醒后使用的是HSI時鐘,此處重啟HSE時鐘,使用PLLCLKSYSCLKConfig_STOP();//獲取重新配置后的時鐘狀態(tài) //時鐘源clock_source_config = RCC_GetSYSCLKSource ();//時鐘頻率RCC_GetClocksFreq(&clock_status_config);
//因為剛喚醒的時候使用的是HSI時鐘,會影響串口波特率,輸出不對,所以在重新配置時鐘源后才使用串口輸出。printf("\r\n重新配置后的時鐘狀態(tài):\r\n");printf(" SYSCLK頻率:%d,\r\n HCLK頻率:%d,\r\n PCLK1頻率:%d,\r\n PCLK2頻率:%d,\r\n 時鐘源:%d (0表示HSI,8表示PLLCLK)\n", clock_status_config.SYSCLK_Frequency, clock_status_config.HCLK_Frequency, clock_status_config.PCLK1_Frequency, clock_status_config.PCLK2_Frequency, clock_source_config);printf("\r\n剛喚醒的時鐘狀態(tài):\r\n"); printf(" SYSCLK頻率:%d,\r\n HCLK頻率:%d,\r\n PCLK1頻率:%d,\r\n PCLK2頻率:%d,\r\n 時鐘源:%d (0表示HSI,8表示PLLCLK)\n", clock_status_wakeup.SYSCLK_Frequency, clock_status_wakeup.HCLK_Frequency, clock_status_wakeup.PCLK1_Frequency, clock_status_wakeup.PCLK2_Frequency, clock_source_wakeup);
PWR—待機模式實驗 (最低功耗的待機模式)
要強調(diào)的是,由于 WKUP 引腳 (PA0) 必須使用上升沿才能喚醒待機狀態(tài)的系統(tǒng),所以我們硬件設(shè)計的 PA0 引腳連接到按鍵 KEY1 ,且按下按鍵的時候會在 PA0 引腳產(chǎn)生上升沿,從而可實現(xiàn)喚醒的功能,按鍵的具體電路請查看配套的原理圖。
/* 使能電源管理單元的時鐘,必須要使能時鐘才能進入待機模式 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);
int main(void)
{ /* 使能電源管理單元的時鐘,必須要使能時鐘才能進入待機模式 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);//檢測復(fù)位來源if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET){LED_BLUE;printf("\r\n 待機喚醒復(fù)位 \r\n");}else{LED_GREEN;printf("\r\n 非待機喚醒復(fù)位 \r\n");}while(1){}
}
/*清除WU狀態(tài)位*/PWR_ClearFlag (PWR_FLAG_WU);/* 使能WKUP引腳的喚醒功能 ,使能PA0*/PWR_WakeUpPinCmd (ENABLE);/* 進入待機模式 */PWR_EnterSTANDBYMode();
在進入待機模式前我們控制了 LED 彩燈為紅色,但在待機狀態(tài)時,由于 I/O 口會處于高阻態(tài),所以 LED 燈會熄滅。
系統(tǒng)喚醒后會進行復(fù)位,從頭開始執(zhí)行上述過程,與第一次上電時不同的是,這樣的復(fù)位會使 PWR_FLAG_WU 標志位改為 SET 狀態(tài),所以這個時候 LED 彩燈會亮藍色。(這也為什么我們可以從while循環(huán)外獲取是否是待機啟動)
PWR—PVD 電源監(jiān)控實驗(如何使用 PVD 監(jiān)控供電電源,增強系統(tǒng)的魯棒性)
中使用 PVD 監(jiān)控 STM32 芯片的 VDD 引腳,當監(jiān)測到供電電壓低于閾值時會產(chǎn)生 PVD 中斷,系統(tǒng)進入中斷服務(wù)函數(shù)進入緊急處理過程。所以進行這個實驗時需要使用一個可調(diào)的電壓源給實驗板供電,改變給 STM32 芯片的供電電壓,為此我們需要先了解實驗板的電源供電系統(tǒng),見圖實驗板的電源供電系統(tǒng)
整個電源供電系統(tǒng)主要分為以下五部分:
- (1) 6-12V 的 DC 電源供電系統(tǒng),這部分使用 DC 電源接口引入 6-12V 的電源,經(jīng)過 RT7272 進行電壓轉(zhuǎn)換成 5V 電源,再與第二部分的“5V_USB”電源線連接在一起。
- (2) 第二部分使用 USB 接口,使用 USB 線從外部引入 5V 電源,引入的電源經(jīng)過電源開關(guān)及保險絲連接到“5V”電源線。
- (3) 第三部分的是電源開關(guān)及保險絲,即當我們的實驗板使用 DC 電源或“5V_USB”線供電時,可用電源開關(guān)控制通斷,保險絲也會起保護作用。
- (4) “5V”電源線遍布整個板子,板子上各個位置引出的標有“5V”絲印的排針都與這個電源線直接相連。5V 電源線給板子上的某些工作電壓為 5V 的芯片供電。5V 電源還經(jīng)過 LDO 穩(wěn)壓芯片,輸出 3.3V 電源連接到“3.3V”電源線。
- (5) 同樣地,“3.3V”電源線也遍布整個板子,各個引出的標有“3.3V”絲印的排針都與它直接相連,3.3V 電源給工作電壓為 3.3V 的各種芯片供電。STM32 芯片的 VDD 引腳就是直接與這個3.3V 電源相連的,所以通過 STM32 的 PVD 監(jiān)控的就是這個“3.3V”電源線的電壓。
軟件設(shè)計:
/*** @brief 配置PVD.* @param None* @retval None*/
void PVD_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;/*使能 PWR 時鐘 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);/* 使能 PVD 中斷 */NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);/* 配置 EXTI16線(PVD 輸出) 來產(chǎn)生上升下降沿中斷*/EXTI_ClearITPendingBit(EXTI_Line16);EXTI_InitStructure.EXTI_Line = EXTI_Line16;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);/* 配置PVD級別PWR_PVDLevel_2V6 (PVD檢測電壓的閾值為2.6V,VDD電壓低于2.6V時產(chǎn)生PVD中斷) *//*具體級別根據(jù)自己的實際應(yīng)用要求配置*/PWR_PVDLevelConfig(PWR_PVDLevel_2V6);/* 使能PVD輸出 */PWR_PVDCmd(ENABLE);
}
/*** @brief PVD中斷請求* @param None* @retval None*/
void PVD_IRQHandler(void)
{/*檢測是否產(chǎn)生了PVD警告信號*/if(PWR_GetFlagStatus (PWR_FLAG_PVDO)==SET) {/* 亮紅燈,實際應(yīng)用中應(yīng)進入緊急狀態(tài)處理 */LED_RED; }/* 清除中斷信號*/EXTI_ClearITPendingBit(EXTI_Line16);}
注意這個中斷服務(wù)函數(shù)的名是 PVD_IRQHandler 而不是 EXTI16_IRQHandler(STM32 沒有這樣的中斷函數(shù)名) ,示例中我們僅點亮了 LED 紅燈,不同的應(yīng)用中要根據(jù)需求進行相應(yīng)的緊急處理。
主函數(shù)
?int main(void)
{ LED_GPIO_Config(); //亮綠燈,表示正常運行LED_GREEN; //配置PVD,當電壓過低時,會進入中斷服務(wù)函數(shù),亮紅燈PVD_Config();while(1){ /*正常運行的程序*/}
}
【 !】實驗操作:
?1.使用外部可調(diào)電源,調(diào)節(jié)成5V輸出,連接到實驗板引出的 5V<--->GND排針給板子供電;
2.復(fù)位實驗板,電壓正常時板子上的LED彩燈應(yīng)為綠色
3.向下調(diào)節(jié)可調(diào)電源的電壓,大約當降至4.2V的時候,LED彩燈會轉(zhuǎn)為紅色。
(程序中控制PVD監(jiān)控電壓約為2.6V,當5V電源降至4.2V的時候,連接STM32的VDD電源(3.3V電源)會低于2.5V,產(chǎn)生PVD事件,在中斷中控制亮紅燈)
【 !!】注意事項:
使用可調(diào)電源給實驗板供電,其它電源線都拔掉(包括下載器、USB線)。
由于直接接排針供電沒有電路保護,調(diào)節(jié)電源時小心不要使供電電壓遠高于5V,電壓太高會燒壞實驗板!!