cancel
Showing results for 
Search instead for 
Did you mean: 

Monitoring VDD using the PVD feature

richard23
Associate II
Posted on December 18, 2013 at 23:00

I am using a STM32F203IGT6 trying to detect low VDD using the PVD feature.  This seems simple, but I cannot make it work.  My initialization code is below.  I start the peripheral clock set the PLS and PVDE bits (CS = 0x00F0), but the PVDO bit is the CSR does not change when I lower VDD from 3.3 to 2.5V.

The reference manual claims that the PVD monitors VDD/VDDA.  Do both of these voltages need to be blow the threshold?

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

    

    PWR->CR |= 0xe0;  //PV26;  // Set power voltage detection threshold 

    PWR->CR |= PVDE;  // Enable power voltage detection  

6 REPLIES 6
jpeacock2399
Associate II
Posted on December 19, 2013 at 15:57

Here's how I set up the PVD to trap Vdd falling below 2.9V, early warning for power fail. Inside the PVDinterupt handler check the register

PWR

->

CSR

&

PWR_CSR_PVDO to determine rising or falling edge on the PVD (e.g. 0 is falling edge, voltage rising above 2.9V).

// Enable the EXTI16 (PVD) Power Supervisor Interrupt 
// EXTI16 rising edge for falling voltage, falling edge for rising voltage on PVD 
NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn; // PVD programmable voltage detect 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = BKPDEV_PVD_PRIORITY; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 
PWR_PVDCmd(DISABLE); // disable PVD before change 
PWR_PVDLevelConfig(PWR_PVDLevel_7); // level falling to trigger powerfail 
PWR_PVDCmd(ENABLE); // enable PVD 
EXTI_ClearITPendingBit(EXTI_Line16); // clear pending IRQs 
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
EXTI_InitStructure.EXTI_Line = EXTI_Line16; // set up irq trigger 
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // trigger power rising edge (voltage drop) 
EXTI_InitStructure.EXTI_LineCmd = ENABLE; // alert if power status changes 
EXTI_Init(&EXTI_InitStructure); 

This gives me a short warning as power drops. How long the CPU will run depends on the discharge rate in the capacitors as Vdd drops, so you can't do much. I save some context in backup RAM so I have a record of the power fail. And yes, monitoring Vdda is important too because it supplies the power to the PLL clock multiplier in addition to the ADC. As the volatge drops on Vdda the PLL will shut down. Jack Peacock
richard23
Associate II
Posted on December 19, 2013 at 18:29

Shouldn't it be posible to monitor the PVDO bit in PWR->CSR without setting up the interrupt?

jpeacock2399
Associate II
Posted on December 20, 2013 at 00:26

Sure, you can poll the PVD status, but you have so little time to react to falling power that you can't guarantee you'll catch the flag in time if you poll occasionally.  And if you do nothing else but poll you don't have any time left for useful work.

richard23
Associate II
Posted on December 23, 2013 at 14:32

The issue is that both VDD and VDDA must be below the threshold for the PVDO bit to be set .  This is the case for the brown out as well.   The board I have has  separate VDD and VDDA.  Hence, the BOR and PVD have no effect when VDD falls below the threshold.

Thanks for your help DeeDeee

jpeacock2399
Associate II
Posted on December 23, 2013 at 23:27

You can monitor Vdda if you can spare a channel on ADC1.  Use the bandgap voltage reference ADC channel, it averages very close to 1.2VDC.  If your Vdda starts to drop the bandgap sample will start to rise.  Set up an analog watchdog interrupt on the bandgap channel, a narrow range for the AWD and a fast sampling rate on ADC1.  Along with the PVD for Vdd you can monitor both voltages.

  Jack Peacock
jfcote
Associate II
Posted on November 24, 2014 at 17:51

I'm using PVD in polling mode and i also got problem with PVD.  I made a function ReadBattery that is a basically a ''for'' loop setting all PVD threshold level one after the other starting with the lowest one (1.9V) until the PVDO bit is set.  Meaning the VDD is now lower than PVD voltage.  When i was in debug mode tracing step-by-step in my code, everything worked fine.  As soon as i removed the breakpoint and execute the code at normal speed, PVD bit is always LOW.  My problem was that i needed a stabilization delay after setting the new threshold level and polling the PVDO bit.  A 1ms delay seems alright.  I did not find anything in datasheet and reference manual regarding a delay.  The delay explains why everyone using PVD with interrupt did not get any problem because regardless the delay, the interrupt will eventually be trigerred.  But while polling PVDO bit in a for loop, you need a delay.