2013-12-18 02:00 PM
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 detection2013-12-19 06:57 AM
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
2013-12-19 09:29 AM
Shouldn't it be posible to monitor the PVDO bit in PWR->CSR without setting up the interrupt?
2013-12-19 03:26 PM
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.
2013-12-23 05:32 AM
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 DeeDeee2013-12-23 02:27 PM
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 Peacock2014-11-24 08:51 AM
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.