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的外设或者模块的操作(配置、使用),在前期的配置中,基本上都是需要使能相应的时钟。

相关推荐
aloneboyooo8 分钟前
PWR-STM32电源控制
stm32·单片机·嵌入式硬件
韦东山23 分钟前
zephyr移植到STM32
stm32·单片机·嵌入式硬件·zephyr
1101 110110 小时前
STM32-笔记36-ADC(模拟/数字转换器)
笔记·stm32·嵌入式硬件
youcans_11 小时前
【动手学电机驱动】STM32-MBD(3)Simulink 状态机模型的部署
stm32·单片机·嵌入式硬件·matlab·代码生成
end_SJ11 小时前
初学STM32 --- USMART
stm32·单片机·嵌入式硬件
我想学LINUX13 小时前
【stm32+K210项目】基于K210与STM32协同工作的智能垃圾分类系统设计与实现(完整工程资料源码)
stm32·单片机·嵌入式硬件·毕业设计·课程设计·项目
end_SJ13 小时前
初学stm32 --- RTC实时时钟
stm32·嵌入式硬件·实时音视频
森旺电子13 小时前
STM32+WIFI获取网络时间+8位数码管显示+0.96OLED显
stm32·单片机·嵌入式硬件
析木不会编程14 小时前
STM32的LED点亮教程:使用HAL库与Proteus仿真
stm32·嵌入式硬件·proteus
Zevalin爱灰灰16 小时前
FreeRTOS从入门到精通 第七章(FreeRTOS列表和列表项)
stm32·操作系统·freertos