stm32之PVD可编程电压监测器(掉电保存数据)

前言:stm32系列提供了可编程电压检测器PVD,它是实时检测VDD的电压,当检测到电压低于或者高于PVD设置的阈值时,会想内核产生一个PVD中断(EXTI线中断)以使内核在复位前进行紧急处理。该电压阈值可通过PWR_CSR设置。

PVD可配置8个等级:

代码设计:

#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来打印调试信息RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能PVD电压检测模块的时钟//通过执行下面两个中断配置函数后,当VDD电压高于或者低于阈值时,就会进入PVD_IRQHandler中断EXTI_Configuration();//配置EXTI_Line16外部中断PVD_NVIC_Configuration();//PVD中断优先级PWR_PVDLevelConfig(PWR_PVDLevel_2V9);//设置PVD阈值PWR_PVDCmd(ENABLE);//使能PVD电压检测while(1){Delay(0xfffff);printf("STM32正常工作中...\r\n");//去掉上面两个中断配置函数,也可以在while循环里不断查询PWR状态来判断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;//上升沿和下降沿都触发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)时钟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_Tx;USART_Init(USART1, &USART_InitStructure);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);
}void Delay(__IO u32 nCount)	 //简单的延时函数
{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("进入PVD中断,电压高于阈值\r\n");}else                                    //低于阈值{printf("进入PVD中断,电压低于阈值\r\n");}      EXTI_ClearITPendingBit(EXTI_Line16);}
}

代码附带了不少注释,相信不难理解。编译下载到板子后,还需要一个可调电源来改变芯片的供电电压,当电压低于或者高于阈值的时候,就会进入PVD_IRQHandler中断,在PC端串口上位机可接受到进入中断打印的信息。

只要电压超过2.0v芯片就能正常工作,不是低于阈值就不能工作。所以在实际运用中,如果是用电池给芯片供电,当电池电量不足时,电池的供电电压就会下降,下降到低于阈值时就会触发PVD中断,那么这时候需要进行数据备份处理或者进行低电量提醒。

如果直接切断电源,进入中断只能维持很短很短的时间,连一句打印信息也无法完整输出。解决这个问题,需要在电源输入点加大电容,当掉电的时候由电容提供电源维持芯片运行一段时候,以做紧急数据保存。所选用电容的参数影响掉电后芯片维持运行的时间,根据掉电中断处理所需的时间长短来选用电容。

 

 

 

<< 骐骥一跃,不能十步;驽马十驾,功在不舍。———荀子 >>


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部