佛山市做网站的公司,建一个手机网站需要多少钱,网上书店网站前端搜索条怎么做,WordPress如何添加表情有时在一些应用中#xff0c;我们需要检测系统是否掉电了#xff0c;或者要在掉电的瞬间需要做一些处理。
STM32内部自带PVD功能#xff0c;用于对MCU供电电压VDD进行监控。
STM32就有这样的掉电检测机制——PVD(Programmable Voltage Detecter)#xff0c;即可编程电压检…有时在一些应用中我们需要检测系统是否掉电了或者要在掉电的瞬间需要做一些处理。
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的外设或者模块的操作配置、使用在前期的配置中基本上都是需要使能相应的时钟。