在實際應(yīng)用場景中,可能會出現(xiàn)設(shè)備電源電壓異常下降或掉電的情況,因此,有時候需要檢測設(shè)備是否掉電,或者在設(shè)備掉電的瞬間做一些緊急關(guān)機處理,比如保存重要的用戶數(shù)據(jù),記錄運行時間,緊急通知其他平臺等等。
1 PVD簡介
1.1 工作原理
STM32本身內(nèi)置了一種掉電檢測機制——PVD(Programmable Voltage Detecter),即可編程電壓檢測器。
其原理是通過PVD監(jiān)測電壓變化,并提前設(shè)定好一個基準(zhǔn)電壓,當(dāng)芯片的供電電壓高于或低于該基準(zhǔn)電壓時便產(chǎn)生PVD中斷,在PVD中斷里面就可以做一些緊急處理。
PVD門限閥值如下圖所示:
1.2 軟件配置步驟
1、初始化配置PVD參數(shù)。
2、在中斷函數(shù)加入緊急處理代碼。
PVD參數(shù)具體配置如下:
通過配置電源/狀態(tài)控制寄存器(PWR_CSR)和電源控制寄存器(PWR_CR)來監(jiān)控電源電壓。
電源控制寄存器(PWR_CR)如下:
其中,PLS[2:0]這幾位選擇監(jiān)控電壓的閥值。PVDE位用來使能PVD。
電源/狀態(tài)控制寄存器(PWR_CSR)如下:
其中,PVDO標(biāo)志用來表明VDD是高于還是低于PVD的電壓閥值。
PVD事件在內(nèi)部連接到外部中斷的第16線,如果該中斷在外部中斷寄存器中是使能的,該事件就會產(chǎn)生中斷。當(dāng)VDD下降到PVD閥值以下和(或)當(dāng)VDD上升到PVD閥值之上時,根據(jù)外部中斷第16線的上升/下降邊沿觸發(fā)設(shè)置,就會產(chǎn)生PVD中斷。通過這一特性可將PVD用于用于執(zhí)行緊急關(guān)閉任務(wù)。
1.3 注意事項
1、如果項目使用了多個外設(shè)中斷,要注意PVD中斷的優(yōu)先級。
2、注意緊急處理代碼的執(zhí)行時間,要在MCU電壓降到完全不能工作前執(zhí)行完(可以通過調(diào)整PVD閾值電壓,或者在MCU供電電源處加大電容以延緩掉電時間)。
3、PVD的閥值觸發(fā)有100mV的遲滯(可能是為了消抖,詳見上面的PVD門限閥值圖),因此,設(shè)置閥值時最好留一點余量。
4、如果PVD中斷觸發(fā)方式使用上升下降沿觸發(fā),在電壓不穩(wěn)定的情況下可能會反復(fù)觸發(fā)中斷,此時可以通過設(shè)置標(biāo)志位來保證緊急代碼只運行1次。
2 程序編寫
參考測試代碼:
/**
* @brief This function handles the PVD Output interrupt request.
* @param None
* @retval None
*/
void PVD_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line16) != RESET)
{
/* 掉電時運行的緊急代碼 */
printf("low power.
");
/* Clear the Key Button EXTI line pending bit */
EXTI_ClearITPendingBit(EXTI_Line16);
}
}
/**
* @brief Configures EXTI Lines.
* @param None
* @retval None
*/
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
/* Configure EXTI Line16(PVD Output) to generate an interrupt on rising and falling edges */
EXTI_ClearITPendingBit(EXTI_Line16);
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);
}
/**
* @brief Configures NVIC and Vector Table base location.
* @param None
* @retval None
*/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the PVD Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void PVD_Init(void)
{
/* Enable PWR and BKP clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/* Configure EXTI Line to generate an interrupt on falling edge */
EXTI_Configuration();
/* NVIC configuration */
NVIC_Configuration();
/* Configure the PVD Level to 2.9V */
PWR_PVDLevelConfig(PWR_PVDLevel_2V9);
/* Enable the PVD Output */
PWR_PVDCmd(ENABLE);
}
int main(void)
{
uart_init(115200);
PVD_Init();
printf("init success.
");
while (1)
{
}
}
示例代碼測試結(jié)果:
結(jié)束語
上面的測試?yán)又皇墙o大家做一個參考,實際上需要根據(jù)項目的具體需求去補充細(xì)節(jié),這里就不再多說了。
好了,關(guān)于STM32如何使用PVD掉電檢測功能就介紹到這里,如果你們還有什么問題,歡迎評論區(qū)留言。
如果這篇文章能夠幫到你,就…懂的。