stm32的掉电检测机制——PVD

有时在一些应用中,我们需要检测系统是否掉电了,或者要在掉电的瞬间需要做一些处理。

STM32内部自带PVD功能,用于对MCU供电电压VDD进行监控。

STM32就有这样的掉电检测机制------PVD(Programmable Voltage Detecter),即可编程电压检测器。通过PVD我们可以设定一个基准电压,当芯片的供电电压高于或低于该基准电压时便产生PVD中断,我们可以在PVD中断里做一些处理。

本文以STM32L051为例,来说明PVD的使用。

以下是STM32L051用户手册中对PVD的描述,根据这张图我们可以知道,PVD中断在内部是连接在中断线16的,软件上可以配置

PVD总共可以设置7个等级, 可以通过PWR_CR寄存器的PLS[2:0]来设置。 通过电源控制寄存器中的PLS[2:0]位可以用来设定监控电压的阀值,通过对外部电压进行比较来监控电源。当条件触发,需要系统进入特别保护状态,执行紧急关闭任务:对系统的一些数据保存起来,同时对外设进行相应的保护操作。

下面是PLS的描述, 其中最后一个等级是特殊的, 它使用PB7引脚的电压和内部基准电压进行比较, 使用这一等级时, PB7必须设置成模拟输入。 一般而言, 我们用前6个等级就足够了, 具体选择哪个等级需要根据自己板子的实际情况来定夺, 例如当MCU是3.3V供电且电源非常稳定时, 就可以选择将阈值设置成3.1V, 这样在掉电时就可以更早的触发PVD中断做紧急处理。

同时也要注意电路上储能电容是否够大, 这会影响PVD中断能处理多少代码, 因为系统很快就要完全断电了。

在软件编程上, PVD的使用非常的简单, 下面是一份HAL库的例子。 PVD的初始化只需要提供2个参数, 一个是PVDLevel, 也就是上文提到的7个等级; 另一个参数是Mode, 即中断的边沿选择或事件的边沿选择, 一般用中断就足够了, 事件没用过。 当设置为双边沿中断时, 可以通过PWR_CSR的PVDO位来判断是上升沿还是下降沿, HAL库已经封装好了相应的宏:

__HAL_PWR_GET_FLAG, 通过__HAL_PWR_GET_FLAG( PWR_FLAG_PVDO )就可以获取PVDO位的状态, 为0则是VDD高于阈值(上电的情况), 为1则是VDD小于阈值(掉电的情况) 。

实测在掉电时, MCU会多次进入PVD中断, 这应该是因为掉电瞬间电压不稳定导致的。 因此如果在掉电前要做一些紧急操作, 要记得加个静态变量标记, 使紧急操作只执行一次。

操作流程:使用HAL库版本

/* 初始化PVD */

void PVD_Init(void)

{

PWR_PVDTypeDef PvdStruct;

HAL_PWR_EnablePVD(); /* 使能PVD */

PvdStruct.PVDLevel = PWR_PVDLEVEL_6; /* PVD阈值3.1V */

PvdStruct.Mode = PWR_PVD_MODE_IT_RISING; /* 检测掉电 */

HAL_PWR_ConfigPVD(&PvdStruct);

HAL_NVIC_SetPriority(PVD_IRQn, 0, 0); /* 配置PVD中断优先级 */

HAL_NVIC_EnableIRQ(PVD_IRQn); /* 使能PVD中断 */

}

/* PVD中断处理 */

void PVD_IRQHandler(void)

{

if(__HAL_PWR_GET_FLAG( PWR_FLAG_PVDO )) /* 1为VDD小于PVD阈值,掉电情况 */

{

/* 掉电前的紧急处理 */

}

}

操作流程:不使用HAL库版本

1)、系统启动后启动PVD,并开启相应的中断。

PWR_PVDLevelConfig(PWR_PVDLevel_2V8); // 设定监控阀值

PWR_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);

...... // 用户添加紧急处理代码处

}

最后顺便说下哪些应用场合会用到PVD, 以下是我工作中遇到过得一些场景。

1.记录设备掉电时间。 这个很好理解, 可能业务上就有这个需求, 或者可以利用这一点来完成低功耗设备的待机时长测试。

2.通知其他处理离线。 假如设备中有由干电池供电的MCU1和由锂电池供电的MCU2, MCU1的部分功能可能需要MCU2来完成, MCU1需要知道MCU2是否离线(因为锂电池可拔插, 可能随时被拔) 。 这种情况就可以在MCU2上利用PVD来通知MCU1。 通知的方式有很多, 例如串口直接通知另一方自己将要断电了。 不过要注意低功耗下的使用场景, 例如STM32进入STOP模式时, 系统时钟是关闭的, 此时串口发送的数据波特率可能不是期望的波特率, 被通知方收到的数据可能是错的, 因此建议将通知方的串口时钟源配置成HSI, 并且将低功耗唤醒后的默认时钟配成HSI, 这样一旦在低功耗状态下进入PVD, 串口发送的数据也不会有问题。

3.PVD所对应的时钟需要使能;对于stm32的外设或者模块的操作(配置、使用),在前期的配置中,基本上都是需要使能相应的时钟。

相关推荐
Caramel_biscuit1 小时前
STM32 CAN学习
stm32·嵌入式硬件·学习
坏柠1 小时前
深入浅出SPI通信协议与STM32实战应用(W25Q128驱动)(理论部分)
stm32·单片机·嵌入式硬件
Invinciblenuonuo4 小时前
STM32八股【5】----- TIM定时器
stm32·单片机·嵌入式硬件
猫猫的小茶馆7 小时前
【PCB工艺】软件是如何控制硬件的发展过程
开发语言·stm32·单片机·嵌入式硬件·mcu·51单片机·pcb工艺
多多*11 小时前
Java设计模式 简单工厂模式 工厂方法模式 抽象工厂模式 模版工厂模式 模式对比
java·linux·运维·服务器·stm32·单片机·嵌入式硬件
Android洋芋11 小时前
C语言深度解析:从零到系统级开发的完整指南
c语言·开发语言·stm32·条件语句·循环语句·结构体与联合体·指针基础
小麦嵌入式17 小时前
Linux驱动开发实战(九):Linux内核pinctrl_map详解与优势分析
linux·c语言·汇编·驱动开发·stm32·嵌入式硬件·硬件工程
傍晚冰川21 小时前
【STM32】最后一刷-江科大Flash闪存-学习笔记
笔记·科技·stm32·单片机·嵌入式硬件·学习·实时音视频
电子艾号哲1 天前
STM32单片机入门学习——第1-2节: [1-1、2]课程和STM32简介
stm32·单片机·学习
触角010100012 天前
MPU6050模块详解:从原理到STM32驱动指南(上) | 零基础入门STM32第八十九步
驱动开发·stm32·单片机·嵌入式硬件·物联网