stm32之PVD可编程电压监测器(掉电保存数据)
前言:stm32系列提供了可編程電壓檢測(cè)器PVD,它是實(shí)時(shí)檢測(cè)VDD的電壓,當(dāng)檢測(cè)到電壓低于或者高于PVD設(shè)置的閾值時(shí),會(huì)想內(nèi)核產(chǎn)生一個(gè)PVD中斷(EXTI線中斷)以使內(nèi)核在復(fù)位前進(jìn)行緊急處理。該電壓閾值可通過PWR_CSR設(shè)置。
PVD可配置8個(gè)等級(jí):
代碼設(shè)計(jì):
#include "stm32f10x.h" #include "stdio.h"static void EXTI_Configuration(void); static void PVD_NVIC_Configuration(void); static void USART1_Config(void); static void Delay(__IO u32 nCount);int main(void) { USART1_Config();//使用串口1來打印調(diào)試信息RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能PVD電壓檢測(cè)模塊的時(shí)鐘//通過執(zhí)行下面兩個(gè)中斷配置函數(shù)后,當(dāng)VDD電壓高于或者低于閾值時(shí),就會(huì)進(jìn)入PVD_IRQHandler中斷EXTI_Configuration();//配置EXTI_Line16外部中斷PVD_NVIC_Configuration();//PVD中斷優(yōu)先級(jí)PWR_PVDLevelConfig(PWR_PVDLevel_2V9);//設(shè)置PVD閾值PWR_PVDCmd(ENABLE);//使能PVD電壓檢測(cè)while(1){Delay(0xfffff);printf("STM32正常工作中...\r\n");//去掉上面兩個(gè)中斷配置函數(shù),也可以在while循環(huán)里不斷查詢PWR狀態(tài)來判斷VDD電壓是否高于或低于閾值,如下#if 0if(PWR_GetFlagStatus(PWR_FLAG_PVDO)){ printf("電壓低于閾值.\r\n");}else{printf("電壓高于閾值.\r\n");}#endif} }void EXTI_Configuration(void) {EXTI_InitTypeDef EXTI_InitStructure;EXTI_DeInit();EXTI_StructInit(&EXTI_InitStructure);EXTI_InitStructure.EXTI_Line = EXTI_Line16;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;//上升沿和下降沿都觸發(fā)EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure); }void PVD_NVIC_Configuration(void) {NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure); }void USART1_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;//配置串口1(USART1)時(shí)鐘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;//一般設(shè)置為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_Tx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE); //使能串口 }int fputc(int ch, FILE *f)//重寫標(biāo)準(zhǔn)庫(kù)的fputc函數(shù) {//將Printf內(nèi)容發(fā)往串口USART_SendData(USART1, (unsigned char) ch);while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET); return (ch); }void Delay(__IO u32 nCount) //簡(jiǎn)單的延時(shí)函數(shù) {for(; nCount != 0; nCount--); }在stm32f10x_it.c文件加入:
void PVD_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line16) != RESET){if(PWR_GetFlagStatus(PWR_FLAG_PVDO)==0) //高于閾值{ printf("進(jìn)入PVD中斷,電壓高于閾值\r\n");}else //低于閾值{printf("進(jìn)入PVD中斷,電壓低于閾值\r\n");} EXTI_ClearITPendingBit(EXTI_Line16);} }代碼附帶了不少注釋,相信不難理解。編譯下載到板子后,還需要一個(gè)可調(diào)電源來改變芯片的供電電壓,當(dāng)電壓低于或者高于閾值的時(shí)候,就會(huì)進(jìn)入PVD_IRQHandler中斷,在PC端串口上位機(jī)可接受到進(jìn)入中斷打印的信息。
只要電壓超過2.0v芯片就能正常工作,不是低于閾值就不能工作。所以在實(shí)際運(yùn)用中,如果是用電池給芯片供電,當(dāng)電池電量不足時(shí),電池的供電電壓就會(huì)下降,下降到低于閾值時(shí)就會(huì)觸發(fā)PVD中斷,那么這時(shí)候需要進(jìn)行數(shù)據(jù)備份處理或者進(jìn)行低電量提醒。
如果直接切斷電源,進(jìn)入中斷只能維持很短很短的時(shí)間,連一句打印信息也無法完整輸出。解決這個(gè)問題,需要在電源輸入點(diǎn)加大電容,當(dāng)?shù)綦姷臅r(shí)候由電容提供電源維持芯片運(yùn)行一段時(shí)候,以做緊急數(shù)據(jù)保存。所選用電容的參數(shù)影響掉電后芯片維持運(yùn)行的時(shí)間,根據(jù)掉電中斷處理所需的時(shí)間長(zhǎng)短來選用電容。
?
?
?
<< 騏驥一躍,不能十步;駑馬十駕,功在不舍。———荀子 >>
總結(jié)
以上是生活随笔為你收集整理的stm32之PVD可编程电压监测器(掉电保存数据)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: stm32之电源管理(实现低功耗)
- 下一篇: stm32之实时时钟RTC(掉电计时保持