STM32F030 voltage monitoring implementation

STM32F030 voltage monitoring implementation

When the STM32 has a power failure, it can detect the power failure, record the occurrence of the power failure or save a small amount of data, and restore the state after the voltage is quickly restored or restarted.

There are two ways to realize voltage monitoring. The first is to use PVD. PVD is Programmable Votage Detector. The function is to monitor the supply voltage. When the supply voltage drops below a given threshold, it can generate An interruption informs the software to do emergency processing. The upper half of the table is the programmable monitoring threshold data. When the power supply voltage is restored to above a given threshold, an interrupt can also be generated to notify the software that the power supply is restored. There is a fixed difference between the power supply drop threshold and the power supply rise PVD threshold. The purpose of introducing this difference is to prevent the voltage from jittering slightly above and below the threshold and frequent interruptions.

Set the monitored voltage value through the PLS[2:0] bits in the power control register (PWR_CR). PLS[2:0] bits are used to select the voltage threshold of the PVD monitoring power supply:

             000:2.2V
             001:2.3V
             010:2.4V
             011:2.5V
             100:2.6V
             101:2.7V
             110:2.8V
             111:2.9V

The PVDO flag in the power control/status register (PWR_CSR) is used to indicate whether VDD is higher or lower than the voltage threshold set by PVD (PVDO=0: VDD is higher than the threshold; PVDO=1, VDD is lower than the threshold ). This event is connected to the 16th line of the external interrupt. If the interrupt is enabled in the external interrupt register, the event will generate an interrupt. When VDD drops below the PVD threshold and/or when VDD rises above the PVD threshold, a PVD interrupt will be generated according to the rising/falling edge trigger setting of the 16th line of the external interrupt. Therefore, the identification of voltage drop or voltage rise can be done by querying the PVDO flag or configuring the interrupt line. It should be noted that this function requires a specific clock to be turned on. Such as (Keil reference code):

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); 

Then set the monitoring voltage threshold and start monitoring:

    PWR_PVDLevelConfig(PWR_PVDLevel_4);//2.6V for power voltage monitoring
	PWR_PVDCmd(ENABLE);

If you need to adjust the monitoring threshold, you can pass the following code:

   	PWR_PVDCmd(DISABLE);
    PWR_PVDLevelConfig(PWR_PVDLevel_7);//2.9V for power voltage monitoring
	PWR_PVDCmd(ENABLE);

Then you can read the status of PVDO through PWR_GetFlagStatus(PWR_FLAG_PVDO), which is equivalent to reading (PWR->CSR)&PWR_CSR_PVDO. Use interrupt recognition to configure external interrupt and interrupt corresponding code. Such as:

    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
 
	EXTI_InitStructure.EXTI_Line = EXTI_Line16;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  //EXTI_Trigger_Rising, EXTI_Trigger_Falling or EXTI_Trigger_Rising_Falling
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;	
	EXTI_Init(&EXTI_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);

Then configure the interrupt response service function:

void PVD_IRQHandler(void)
{
	if(PWR_GetFlagStatus(PWR_FLAG_PVDO))     
	{
		//Do something
	} 
	EXTI_ClearITPendingBit(EXTI_Line16); 		

However, some STM32F030 series chips have no internal PVD circuit, so the above functions cannot be used. See the following figure for details:
Insert picture description here
Therefore, if you use, for example, STM32F030K6T6 or some models, you need to use another voltage detection method, that is, monitor Vrefint, and continuously sample the Vrefint voltage through the ADC-DMA method, and in the main loop , Continue to detect and deal with when the voltage drops or rises to a certain threshold. (For the principle, please refer to https://blog.csdn.net/hwytree/article/details/103333769). The implementation code for STM32F030K6T6 is as follows.
The following is the adc1.h part of ADC-DMA:

#ifndef __ADC1_H
#define __ADC1_H

#include "stm32f0xx.h"
#include "stm32f0xx_adc.h"
#define ADC1_DR_Address                0x40012440

extern  uint16_t STM32_Vrefint;
void ADC1_DMA_Init(void);
#endif

The following is the adc1.c part of ADC-DMA:

#include "ADC1.h"
void ADC1_DMA_Init(void)
{
  DMA_InitTypeDef     DMA_InitStructure;
  ADC_InitTypeDef     ADC_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);		
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
	
  ADC_DeInit(ADC1);
  DMA_DeInit(DMA1_Channel1);	
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(&STM32_Vrefint);
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
		  
  DMA_Cmd(DMA1_Channel1, ENABLE);
  ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular); 
  ADC_DMACmd(ADC1, ENABLE); 	
	
  ADC_StructInit(&ADC_InitStructure);
	
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; 
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward; 
  ADC_Init(ADC1, &ADC_InitStructure);  
	
  ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint ,ADC_SampleTime_239_5Cycles); 
  ADC_VrefintCmd(ENABLE);
	
  ADC_GetCalibrationFactor(ADC1); 
  ADC_Cmd(ADC1, ENABLE);  
  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN)); 
  ADC_StartOfConversion(ADC1); 			
}

Then start ADC-DMA before entering the cycle program in the main program:

 uint16_t STM32_Vrefint;
 
ADC1_DMA_Init();

Then STM32_Vrefint is the Vrefint sampling value updated by continuous ADC-DMA. When powered by 3.3V, it is approximately equal to 1.2/3.3*4096. STM company records the Vrefint test calibration value of STM32F030 at 3.3V in a specific 16-bit register before the chip leaves the factory, which can be obtained through the following access methods:

(*((uint16_t *)(0x1FFFF7BA)))

Therefore, when the corresponding supply voltage is 2.9V, the corresponding calibration threshold is

(*((uint16_t *)(0x1FFFF7BA)))*3.3/2.9

When the supply voltage increases, STM32_Vrefint will decrease, and when the supply voltage decreases, STM32_Vrefint will increase. If the value of STM32_Vrefint is lower than the above threshold, it can be considered that the voltage (for example, the original supply voltage is 3.3V) has fallen from 3.3V to 2.9V.

The above is the way of STM32F030 power supply voltage monitoring. Because the PVD method is not available, the ADC-DMA method is the best choice. If the DMA method is not used, the main program continues to control the read ADC, which will introduce a bad delay. Because of the capacitance effect in the circuit, the power supply voltage changes at a non-high-speed level. Through the ADC-DMA method, it can meet the tracking requirements of the voltage changes in time, and make corresponding treatments when it drops or rises to a specific threshold.

-End-

Guess you like

Origin blog.csdn.net/hwytree/article/details/106694331