STM32 PVD的使用(掉电检测)

有时在一些应用中,我们需要检测系统是否掉电了,或者要在掉电的瞬间需要做一些处理。STM32就有这样的掉电检测机制——PVD(Programmable Voltage Detecter),即可编程电压检测器。通过PVD我们可以设定一个基准电压,当芯片的供电电压高于或低于该基准电压时便产生PVD中断,我们可以在PVD中断里做一些处理。本文以STM32L051为例,来说明PVD的使用。

以下是STM32L051用户手册中对PVD的描述,根据这张图我们可以知道,PVD中断在内部是连接在中断线16的,软件上可以配置需要上升沿中断还是下降沿中断,也可以设置双边沿触发,这和GPIO中断有点类似。若设置了双边沿触发,则上电当VDD超过PVD阈值时产生下降沿中断;掉电时VDD低于PVD阈值产生上升沿中断。图中的100mv是滞后,所以准确地说,在掉电时是要当VDD电压小于(PVD阈值-100mv)时才会触发PVD中断。

图1 PVD介绍

PVD总共可以设置7个等级,可以通过PWR_CR寄存器的PLS[2:0]来设置。下面是PLS的描述,其中最后一个等级是特殊的,它使用PB7引脚的电压和内部基准电压进行比较,使用这一等级时,PB7必须设置成模拟输入。一般而言,我们用前6个等级就足够了,具体选择哪个等级需要根据自己板子的实际情况来定夺,例如当MCU是3.3V供电且电源非常稳定时,就可以选择将阈值设置成3.1V,这样在掉电时就可以更早的触发PVD中断做紧急处理。同时也要注意电路上储能电容是否够大,这会影响PVD中断能处理多少代码,因为系统很快就要完全断电了。

图2  PWR_CR的PLS介绍

在软件编程上,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小于阈值(掉电的情况)。

/* 初始化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阈值,掉电情况 */
    {
        /* 掉电前的紧急处理 */
    }
}

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

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

2.通知其他处理离线。假如设备中有由干电池供电的MCU1和由锂电池供电的MCU2,MCU1的部分功能可能需要MCU2来完成,MCU1需要知道MCU2是否离线(因为锂电池可拔插,可能随时被拔)。这种情况就可以在MCU2上利用PVD来通知MCU1。通知的方式有很多,例如串口通知。如果掉电过快串口通知无法实现,那么可以使用GPIO中断通知,例如MCU2在PVD中断唤醒MCU1,一小段时间后MCU1发现MCU2还没有发数据过来,便发送心跳包给MCU2,因为MCU2已经掉电肯定不会应答,MCU1收不到应答就可以认为MCU2离线了。

猜你喜欢

转载自blog.csdn.net/qq_27575841/article/details/107602983