本帖最后由 正点原子运营 于 2023-7-27 11:43 编辑
第二十九章 低功耗实验
1)实验平台:正点原子探索者STM32F407开发板
2) 章节摘自【正点原子】STM32F407开发指南 V1.1
6)STM32技术交流QQ群:151941872
本章,我们将介绍STM32F407的电源控制(PWR),并实现低功耗模式相关功能。我们将通过四个实验来学习并实现低功耗相关功能,分别是PVD电压监控实验、睡眠模式实验、停止模式实验和待机模式实验。 本章分为如下几个小节: 29.1 电源控制(PWR)简介 29.2 PVD电压监控实验 29.3 睡眠模式实验 29.4 停止模式实验 29.5 待机模式实验
29.1 电源控制(PWR)简介电源控制部分(PWR)概述了不同电源域的电源架构以及电源配置控制器。PWR的内容比较多,我们把它们的主要特性概括为以下3点: 电源系统:USB稳压器、内核域(VCORE)、VDD域、备份域、模拟域(VDDA)。 电源监控:POR/PDR监控器、BOR监控器、PVD监控器、AVD监控器、VBAT阈值、温度阈值。 电源管理:VBAT电池充电、工作模式、电压调节控制、低功耗模式。 下面将分别对这3个特性进行简单介绍。
29.1.1 电源系统为了方便对电源系统进行管理,设计者把STM32的内核和外设等器件根据功能划分了不同的电源区域,具体如图29.1.1.1所示。 在电源概述框图中我们划分了3个区域①②③,分别是独立的A/D转换器供电和参考电压、电压调节器、电池备份区域。下面分别进行简单介绍:
① 电池备份区域(后备供电区域) 电池备份区域也就是后备供电区域,使用电池或者其他电源连接到VBAT脚上,当VDD断电时,可以保存备份寄存器的内容和维持RTC的功能。同时VBAT引脚也为RTC、SRAM和LSE振荡器供电,这保证了当主要电源被切断时,RTC能够继续工作。切换到VBAT供电由复位模块中的掉电复位功能控制。
② 电压调节器(VDD /1.2V供电区域) 嵌入式线性调压器为备份域和待机电路以外的所有数字电路供电。调压器输出电压约为 1.2 V。此调压器需要将两个外部电容连接到专用引脚 VCAP_1和VCAP_2,所有封装都配有这两个引脚。为激活或停用调压器,必须将特定引脚连接到 VSS 或 VDD。具体引脚与封装有关。通过软件激活时,调压器在复位后始终处于使能状态。
根据应用模式的不同,可采用三种不同的模式工作。在运转模式下,调节器以正常工号模式为内核、内存和外设提供1.2V;在停止模式下,调节器以低功耗模式提供1.2V电源,以保存寄存器和SRAM的内容。在待机模式下,调节器停止供电,除了备用电路和备份域外,寄存器和SRAM的内容全部丢失。
③ 独立的A/D转换器供电和参考电压(VDDA供电区域) 为了提高转换精度,ADC配有独立电源,可以单独滤波并屏蔽PCB上的噪声。ADC电源电压从单独的VDDA引脚接入,VSSA提供了独立的电源接地连接。为了确保测量低电压时具有更高的精度,用户可以再VREF上连接到单独的ADC外部参考电压输入,VREF电压介于1.8V到VDDA之间。
29.1.2 电源监控电源监控的部分我们主要关注PVD监控器,此外还需要知道上电复位(POR)/掉电复位(PDR)。其他部分的内容请大家查看《STM32F4xx参考手册_V4(中文版).pdf》(5.2节 90页)。
l 上电复位(POR)/掉电复位(PDR) 上电时,当VDD低于指定VPOR阈值时,系统无需外部复位电路便会保持复位模式。一旦VDD电源电压高于VPOR阈值,系统便会退出复位状态,芯片正常工作。掉电时,当VDD低于指定VPDR阈值时,系统就会保持复位模式。如图29.1.2.1所示。 l 欠压复位(BOR) 上电期间,欠压复位(BOR)将使系统保持复位状态,直到VDD电源电压达到指定的VBOR阈值。VBOR阈值通过系统选项字节(某些寄存器的BOR_LEV位)进行配置。默认情况下,BOR关闭。可选择以下可编程VBOR阈值:
欠压复位的描述波形图如图29.1.2.2所示。 l 可编程电压检测器(PVD) 上面介绍的POR、PDR以及BOR功能都是设置电压阈值与外部供电电压VDD比较,当VDD低于设置的电压阈值时,就会直接进入复位状态,防止电压不足导致的误操作。 下面介绍可编程电压检测器(PVD),它可以实时监视VDD的电压,方法是将VDD与PWR控制寄存器1(PWR_CR1)中的PLS[2:0]位所选的VPVD阈值进行比较。当检测到电压低于VPVD阈值时,如果使能EXTI16线中断(即使能PVD & AVD中断),可以产生PVD中断,具体取决于EXTI16线配置为检测上升还是下降沿,然后在复位前,在中断服务程序中执行紧急关闭系统等任务。PVD阀值检测波形,如图29.1.2.1所示。 PVD阀值有8个等级,有上升沿和下降沿的区别,分别就是图29.1.2.3中PVDrise电压为上升沿阀值,PVDfall为下降沿阀值,具体如表29.1.2.2所示。 29.1.3 电源管理电源管理的部分我们要关注低功耗模式,在STM32的正常工作中,具有四种工作模式,运行、睡眠、停止以及待机。在上电复位后,STM32处于运行状态时,当内核不需要继续运行,就可以选择进入后面的三种模式降低功耗。这三种低功耗模式电源消耗不同、唤醒时间不同和唤醒源不同,我们要根据自身的需要选择合适的低功耗模式。 下面是低功耗模式汇总介绍,如下表所示。 下面对睡眠模式、停止模式和待机模式的进入及退出方法进行介绍。
1、睡眠模式 进入睡眠模式,CPU时钟关闭,但是其他所有的外设仍可以运行,所以任何中断或事件都可以唤醒睡眠模式。有两种方式进入睡眠模式,这两种方式进入的睡眠模式唤醒的方法不同,分别是 WFI(wait for interrupt)和 WFE(wait forevent),即由等待“中断”唤醒和由“事件”唤醒。下面我们看看睡眠模式进入及退出方法: 2、停止模式 进入停止模式,所有的时钟都关闭,所有的外设也就停止了工作。但是VDD电源是没有关闭的,所以内核的寄存器和内存信息都保留下来,等待重新开启时钟就可以从上次停止的地方继续执行程序。 值得注意的是:当电压调节器处于低功耗模式下,当系统从停止模式退出时,将会有一段额外的启动延时。如果在停止模式期间保持内部调节器开启,则退出启动时间会缩短,但相应的功耗会增加。 3、待机模式 待机模式可实现最低功耗。该模式是在CM4深睡眠模式时关闭电压调节器,整个1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。除备份域(RTC寄存器、RTC备份寄存器和备份SRAM)和待机电路中的寄存器外,SRAM 和其他寄存器内容都将丢失。不过如果我们使能了备份区域(备份SRAM、RTC、LSE),那么待机模式下的功耗,将达到6uA左右。
那么我们如何进入待机模式呢?其实很简单,只要按表29.1.3.3所示的步骤执行就可以了: 29.2 PVD电压监控实验本小节我们来学习PVD电压监控实验,该部分的知识点内容请回顾29.1.2电源监控。我们直接从寄存器介绍开始。
29.2.1 PWR寄存器本实验用到PWR的部分寄存器,在《STM32F4xx参考手册_V4(中文版).pdf》手册的5.4小节(100页)可以找到PWR的寄存器描述。这里我们只介绍PVD电压监控实验我们用到的PWR的控制寄存器(PWR_CR),还有就是我们要用到EXTI16线中断,所以还要配置EXTI相关的寄存器,具体如下: l PWR控制寄存器(PWR_CR) PWR控制寄存器1描述如图29.2.1.1所示: 位[7:5]PLS用于设置PVD检测的电压阀值,就是前面我们介绍PVD的8个等级阀值选择。 PVDE位,用于使能或者禁止PVD检测,显然我们要使能PVD检测,该位置1。 这个寄存器还有其它的位我们没有列出来,也是跟电源相关的,如待机,掉电等,我们后面的实验再讲解这些功能,这里先跳过。
l EXTI中断屏蔽寄存器(EXTI_IMR) EXTI中断屏蔽寄存器描述如图29.2.1.2所示: 我们要使用到EXTI16线中断,所以MR16位要置1,即开放来自EXTI16线的中断请求。
l EXTI上升沿触发选择寄存器(EXTI_RTSR) EXTI上升沿触发选择寄存器描述如图29.2.1.3所示: 我们要使用到EXTI16线中断,所以TR16位要置1,即允许EXTI16线上的下降沿触发。
l EXTI下降沿触发选择寄存器(EXTI_FTSR) EXTI下降沿触发选择寄存器描述如图29.2.1.4所示: 我们要使用到EXTI16线中断,所以TR16位要置1,即允许EXTI16线上的下降沿触发。
l EXTI挂起寄存器(EXTI_PR) EXTI挂起寄存器描述如图29.2.1.5所示: EXTI挂起寄存器EXTI_PR管理的是EXTI0线到EXTI19线的中断标志位。在PVD中断服务函数里面,我们记得要对PR16位写1,来清除EXTI16线的中断标志。
29.2.2 硬件设计1. 例程功能 开发板供电正常的话,LCD屏会显示"PVD Voltage OK!"。当供电电压过低,则会通过PVD中断服务函数将LED1点亮;当供电电压正常,会在PVD中断服务函数将LED1熄灭。LED0闪烁,提示程序运行。
2. 硬件资源 1)LED灯 LED0 – PF9 LED1 – PF10 2)PVD(可编程电压监测器) 3)正点原子 2.8/3.5/4.3/7寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
3. 原理图 PVD属于STM32F407的内部资源,只需要软件设置好即可正常工作。我们通过LED0和LCD来指示进入PVD中断的情况。
29.2.3 程序设计29.2.3.1 PWR的HAL库驱动 PWR在HAL库中的驱动代码在stm32f4xx_hal_pwr.c文件(及其头文件)中。
1. HAL_PWR_ConfigPVD函数 PVD的初始化函数,其声明如下: - voidHAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD);
复制代码l 函数描述: 用于初始化PWR。
l 函数形参: 形参1是PWR_PVDTypeDef结构体类型变量,其定义如下: - typedef struct
- {
- uint32_t PVDLevel; /* 指定PVD检测级别 */
- uint32_t Mode; /* 指定PVD的EXTI检测模式 */
- }PWR_PVDTypeDef;
复制代码1)PVDLevel:指向PVD检测级别,对应PWR_CR寄存器的PLS位的设置,取值范围PWR_PVDLEVEL_0到PWR_PVDLEVEL_7,共八个级别。 2)Mode:指定PVD的EXTI边沿触发模式。
l 函数返回值: 无
PVD电压监控配置步骤1)配置PVD,使能PVD时钟。 调用HAL_PWR_ConfigPVD函数配置PVD,包括检测电压级别、使用中断线触发方式等。
2)使能PVD检测,配置PVD/AVD中断优先级,开启PVD中断。 通过HAL_PWR_EnablePVD函数使能PVD检测。 通过HAL_NVIC_EnableIRQ函数使能PVD中断。 通过HAL_NVIC_SetPriority函数设置中断优先级。
3)编写中断服务函数。 PVD中断服务函数为PVD_IRQHandler,当发生中断的时候,程序就会执行中断服务函数。HAL库有专门的PVD中断处理函数,我们只需要在PVD中断服务函数里面调用HAL_PWR_PVD_IRQHandler()函数,然后逻辑代码在PVD中断服务回调函数HAL_PWR_PVDCallback中编写,详见本例程源码。
29.2.3.2 程序流程图 下面看看本实验的程序流程图: 图29.2.3.2.1 PVD电压监控实验程序流程图 29.2.3.3 程序解析 这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。PWR源码包括两个文件:pwr.c和pwr.h。该章节有四个实验,每一个实验的代码都是在上一个实验后面追加。
pwr.h头文件只有函数声明,下面直接开始介绍pwr.c的程序,首先是PVD初始化函数。 - /**
- * @brief 初始化PVD电压监视器
- * @param pls: 电压等级(PWR_PVD_detection_level)
- * @arg PWR_PVDLEVEL_0,2.2V;
- * @arg PWR_PVDLEVEL_1,2.3V;
- * @arg PWR_PVDLEVEL_2,2.4V;
- * @arg PWR_PVDLEVEL_3,2.5V;
- * @arg PWR_PVDLEVEL_4,2.6V;
- * @arg PWR_PVDLEVEL_5,2.7V;
- * @arg PWR_PVDLEVEL_6,2.8V;
- * @arg PWR_PVDLEVEL_7,2.9V;
- * @retval 无
- */
- void pwr_pvd_init(uint32_t pls)
- {
- PWR_PVDTypeDefpvd_handle = {0};
- __HAL_RCC_PWR_CLK_ENABLE(); /*使能PWR时钟*/
-
- pvd_handle.PVDLevel = pls;
- /*使用中断线的上升沿和下降沿双边缘触发*/
- pvd_handle.Mode =PWR_PVD_MODE_IT_RISING_FALLING;
- HAL_PWR_ConfigPVD(&pvd_handle); /* 开启PWR对应的lin16上的中断 */
- HAL_NVIC_SetPriority(PVD_IRQn, 3 ,3); /* 组2,最低优先级 */
- HAL_NVIC_EnableIRQ(PVD_IRQn);
- HAL_PWR_EnablePVD();
- }
复制代码这里需要注意的就是PVD中断线选择的是上升沿和下降沿双边缘触发,其他的内容前面已经讲过。
下面介绍的是PVD中断服务函数及其回调函数,函数定义如下: - /**
- * @brief PVD中断服务函数
- * @param 无
- * @retval 无
- */
- void PVD_IRQHandler(void)
- {
- HAL_PWR_PVD_IRQHandler();
- }
- /**
- * @brief PVD中断服务回调函数
- * @param 无
- * @retval 无
- */
- voidHAL_PWR_PVDCallback(void)
- {
- if (__HAL_PWR_GET_FLAG(PWR_FLAG_PVDO)) /* 电压比PLS所选电压还低 */
- {
- /* LCD显示电压低 */
- lcd_show_string(30, 130, 200, 16, 16, "PVD LowVoltage!", RED);
- LED1(0); /* 点亮LED1, 表明电压低了 */
- }
- else
- {
- /* LCD显示电压正常 */
- lcd_show_string(30, 130, 200, 16, 16, "PVD VoltageOK! ", BLUE);
- LED1(1); /* 灭掉绿灯 */
- }
- }
复制代码HAL_PWR_PVDCallback回调函数中首先是判断VDD电压是否比PLS所选电压还低,是的话,就在LCD显示PVD Low Voltage!并且点亮LED1,否则,在LCD显示PVD Voltage OK!并且关闭LED1。
在main函数里面编写如下代码: - int main(void)
- {
- uint8_t t=0;
- HAL_Init(); /* 初始化HAL库 */
- sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟, 168Mhz */
- delay_init(168); /* 延时初始化 */
- usart_init(115200); /* 串口初始化为115200 */
- led_init(); /* 初始化LED */
- lcd_init(); /* 初始化LCD */
- pwr_pvd_init(PWR_PVDLEVEL_7); /* PVD 2.9V检测 */
- lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
- lcd_show_string(30, 70, 200, 16, 16, "PVD TEST", RED);
- lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
- /* 默认LCD显示电压正常 */
- lcd_show_string(30, 130, 200, 16, 16, "PVD Voltage OK! ", BLUE);
- while (1)
- {
- if ((t % 20) == 0)
- {
- LED0_TOGGLE(); /* 每200ms,翻转一次LED0 */
- }
- delay_ms(10);
- t++;
- }
- }
复制代码这里我们选择PVD的检测电压阀值为2.9V,其他的代码很好理解,最后下载验证一下。
29.2.4 下载验证下载代码后,默认LCD屏会显示"PVD Voltage OK!",当供电电压过低,则LED1会点亮,并且LCD屏会显示PVD Low Voltage!。当开发板供电正常,LED1会熄灭,LCD屏会继续显示"PVD Voltage OK!"。 |