STM32 可编程电压监测器(PVD)

2019-07-21 00:42发布

   1)PVD = Programmable Votage Detector 可编程电压监测器   它的作用是监视供电电压,在供电电压下降到给定的阀值以下时,产生一个中断,通知软件做紧急处理。在给出表格的上半部分就是可编程的监视阀值数据。当供电电压又恢复到给定的阀值以上时,也会产生一个中断,通知软件供电恢复。供电下降的阀值与供电上升的PVD阀值有一个固定的差值,这就是表中的VPVDhyst(PVD迟滞)这个参数,通过列出的PVD阀值数据可以看到这个差别。引入这个差值的目的是为了防止电压在阀值上下小幅抖动,而频繁地产生中断。  
    2)POR = Power On Reset 上电复位;PDR = Power Down Reset 掉电复位。  OR的功能是在VDD电压由低向高上升越过规定的阀值之前,保持芯片复位,当越过这个阀值后的一小段时间后(图中的"滞后时间"或表中的"复位迟滞"),结束复位并取复位向量,开始执行指令。这个阀值就是表中倒数第4行(min=1.8,typ=1.88,max=1.96)。  OR的功能是在VDD电压由高向低下降越过规定的阀值后,将在芯片内部产生复位,这个阀值就是表中倒数第3行(min=1.84,typ=1.92,max=2.0)。     3)可以看到POR比PDR大了0.04V,这就是表中倒数第2行,VPDRhyst(PDR迟滞)=40mV。  
    4)从上面的第2张图可以看到,当VDD上升越过POR阀值时,内部并不马上结束复位,而是等待一小段时间(Reset temporization),这就是表中的最后一行TRSTTEMPO,它的典型数值是2.5ms。  这个滞后时间是为了等待供电电压能够升高到最低可靠工作电压以上,我们看到POR阀值最小只有1.8V,最大也只有1.96V,都低于数据手册中给出的最低可靠工作电压2.0V,所以这个滞后时间是十分必要的,如果供电电压上升缓慢,尤其是从1.8V升到2.0V以上超过1~2.5ms,则很可能造成上电复位后MCU不能正常工作的情况。   
    STM32内部自带PVD功能,用于对MCU供电电压VDD进行监控。通过电源控制寄存器中的PLS[2:0]位可以用来设定监控电压的阀值,通过对外部 电压进行比较来监控电源。当条件触发,需要系统进入特别保护状态,执行紧急关闭任务:对系统的一些数据保存起来,同时对外设进行相应的保护操作。  操作流程:  
    1)、系统启动后启动PVD,并开启相应的中断。  
    WR_PVDLevelConfig(PWR_PVDLevel_2V8); // 设定监控阀值  
    WR_PVDCmd(ENABLE); // 使能PVD  
    EXTI_StructInit(&EXTI_InitStructure);  
    EXTI_InitStructure.EXTI_Line = EXTI_Line16; // PVD连接到中断线16上  
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //使用中断模式  
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Raising;//电压低于阀值时产生中断  
    EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能中断线  
    EXTI_Init(&EXTI_InitStructure); // 初始  
    EXTI_InitStructure.EXTI_Trigger的赋值可选项:  
    EXTI_Trigger_Rising---表示电压从高下降到低于设定阀值时产生中断;  
    EXTI_Trigger_Falling---表示电压从低上升到高于设定阀值时产生中断;  
    EXTI_Trigger_Rising_Falling---表示电压上升或下降越过设定阀值时都产生中断。  
2)、当工作电压低于设定阀值时,将产生PVD中断,在中断程序中进行相应的处理:  
void PVD_IRQHandler(void)
{  
    EXTI_ClearITPendingBit(EXTI_Line16);  
    …… // 用户添加紧急处理代码处  
}
-----------------------------------------------------------------------------------搬运-------------------------------------------------------------------------------------------
亲测:
[mw_shl_code=c,true]u32 num = 0; void PWR_PVD_Init(void) { NVIC_InitTypeDef NVIC_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能PWR时钟 NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn; //使能PVD所在的外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); EXTI_StructInit(&EXTI_InitStructure); EXTI_InitStructure.EXTI_Line = EXTI_Line16; //PVD连接到中断线16上 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //使用中断模式 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //电压低于阀值时产生中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断线 EXTI_Init(&EXTI_InitStructure); //初始 PWR_PVDLevelConfig(PWR_PVDLevel_2V8);//设定监控阀值 PWR_PVDCmd(ENABLE);//使能PVD } void PVD_IRQHandler(void) { EXTI_ClearITPendingBit(EXTI_Line16);//清中断 num = BKP_ReadBackupRegister(BKP_DR10); num++; //用户添加紧急处理代码处 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//使能PWR和BKP外设时钟 PWR_BackupAccessCmd(ENABLE);//使能后备寄存器访问 BKP_WriteBackupRegister(BKP_DR10, (u8)num);//启动界面 }[/mw_shl_code]



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
31条回答
solo
2019-07-23 11:30
为什么我在战舰板的跑马灯测试代码中加了这段代码后,只能进掉电中断,无法进上电中断?(掉电是LED0会闪一下,但上电时LED0不亮)

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"

void PWR_PVD_Init(void)
{   
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
     
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//??PWR??

    NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn;           //??PVD?????????
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//?????1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;       //????0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //????????
    NVIC_Init(&NVIC_InitStructure);
     
    EXTI_StructInit(&EXTI_InitStructure);
    EXTI_InitStructure.EXTI_Line = EXTI_Line16;             //PVD??????16?
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;     //??????
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  //???????????
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;               //?????
    EXTI_Init(&EXTI_InitStructure);                         //??
     
    PWR_PVDLevelConfig(PWR_PVDLevel_2V8);//??????
    PWR_PVDCmd(ENABLE);//??PVD     
}

void PVD_IRQHandler(void)
{
        EXTI_ClearITPendingBit(EXTI_Line16);//clear bit;
        if(PWR_GetFlagStatus(PWR_FLAG_PVDO))
        {
            LED_Init();                          //3õê¼»ˉóëLEDᬽóμÄó2¼t½ó¿ú
            LED0 = 0;
        }
}
  
/************************************************
ALIENTEKÕ½½¢STM32¿a·¢°åêμÑé1
ÅüÂíμÆêμÑé
¼¼êõÖ§3Ö£owww.openedv.com
ìÔ±|μêÆì£ohttp://eboard.taobao.com
1Øע΢DÅ1«Öúƽì¨Î¢DÅoÅ£o"ÕyμãÔ-×ó"£¬Ãa·Ñ»ñè¡STM32×êáÏ¡£
1ãÖYêDDÇòíμç×ó¿Æ¼¼óDÏT1«Ë¾  
×÷ÕߣoÕyμãÔ-×ó @ALIENTEK
************************************************/

int main(void)
{       
        delay_init();            //Ñóê±oˉêy3õê¼»ˉ
        //LED_Init();                          //3õê¼»ˉóëLEDᬽóμÄó2¼t½ó¿ú
        //delay_ms(5000);
   
    PWR_PVD_Init();
    while(1);
   
        while(1)
        {
                LED0=0;
                LED1=1;
                delay_ms(1000);         //Ñóê±300ms
                LED0=1;
                LED1=0;
                delay_ms(1000);        //Ñóê±300ms
        }
}

一周热门 更多>