电源管理—实现低功耗

38.1. 电源管理相关的库函数及命令

STM32HAL库对电源管理提供了完善的函数及命令,使用它们可以方便地进行控制,本小节对这些内容进行讲解。

38.1.1. 配置PVD监控功能

PVD可监控VDD的电压,当它低于阈值时可产生PVD中断以让系统进行紧急处理,这个阈值可以直接使用库函数PWR_PVDLevelConfig配置成前面 表38_1 中说明的阈值等级。

38.1.2. WFI与WFE命令

我们了解到进入各种低功耗模式时都需要调用WFI或WFE命令,它们实质上都是内核指令,在库文件core_cm3.h中把这些指令封装成了函数,见 代码清单38_1

代码清单 38‑1 WFI与WFE的指令定义(core_cm3.h文件)

 /** brief  等待中断

     等待中断 是一个暂停执行指令
     暂停至任意中断产生后被唤醒
 */
 #define __WFI                             __wfi


 /** brief  等待事件

     等待事件 是一个暂停执行指令
     暂停至任意事件产生后被唤醒
 */
 #define __WFE                             __wfe

对于这两个指令,我们应用时一般只需要知道,调用它们都能进入低功耗模式,需要使用函数的格式“__WFI();”和“__WFE();”来调用(因为__wfi及__wfe是编译器内置的函数,函数内部调用了相应的汇编指令)。其中WFI指令决定了它需要用中断唤醒,而WFE则决定了它可用事件来唤醒,关于它们更详细的区别可查阅《cortex-CM3/CM4权威指南》了解。

38.1.3. 进入停止模式

直接调用WFI和WFE指令可以进入睡眠模式,而进入停止模式则还需要在调用指令前设置一些寄存器位, STM32HAL库把这部分的操作封装到HAL_PWR_EnterSTOPMode函数中了,它的定义 见 代码清单38_2

代码清单 40‑2 进入停止模式

 /**
 * @brief 进入停止模式
 * @note 在停止模式下所有I/O都会保持在停止前的状态
 * @note 从停止模式唤醒后,会使用HSI作为时钟源
 * @note 调压器若工作在低功耗模式,可减少功耗,但唤醒时会增加延迟
 * @param Regulator: 设置停止模式时调压器的工作模式
 *        @arg PWR_MAINREGULATOR_ON: 调压器正常运行
 *        @arg PWR_LOWPOWERREGULATOR_ON: 调压器低功耗运行
 * @param STOPEntry: 设置使用WFI还是WFE进入停止模式
 *        @arg PWR_STOPENTRY_WFI: WFI进入停止模式
 *        @arg PWR_STOPENTRY_WFE: WFE进入停止模式
 * @retval None
 */
 void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
 {
     uint32_t tmpreg = 0;

     /* 检查参数是否合法 */
     assert_param(IS_PWR_REGULATOR(Regulator));
     assert_param(IS_PWR_STOP_ENTRY(STOPEntry));

     /* 设置调压器的模式 ---------------------------------*/
     tmpreg = PWR->CR1;
     /* 清除 PDDS 及 LPDS 位 */
     tmpreg &= (uint32_t)~(PWR_CR1_PDDS | PWR_CR1_LPDS);

     /* 根据PWR_Regulator 的值(调压器工作模式)配置LPDS,MRLVDS及LPLVDS位 */
     tmpreg |= Regulator;

     /* 写入参数值到寄存器 */
     PWR->CR1 = tmpreg;

     /* 设置内核寄存器的SLEEPDEEP位 */
     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

     /* 设置进入停止模式的方式 -----------------------------------------------*/
     if (STOPEntry == PWR_STOPENTRY_WFI) {
         /* 需要中断唤醒 */
         __WFI();
     } else {
         /* 需要事件唤醒 */
         __SEV();
         __WFE();
         __WFE();
     }
     /* 以下的程序是当重新唤醒时才执行的,清除SLEEPDEEP位的状态 */
     SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk);
 }

这个函数有两个输入参数,分别用于控制调压器的模式及选择使用WFI或WFE停止,代码中先是根据调压器的模式配置PWR_CR寄存器,再把内核寄存器的SLEEPDEEP位置1,这样再调用WFI或WFE命令时,STM32就不是睡眠,而是进入停止模式了。函数结尾处的语句用于复位SLEEPDEEP位的状态,由于它是在WFI及WFE指令之后的,所以这部分代码是在STM32被唤醒的时候才会执行。

要注意的是进入停止模式后,STM32的所有I/O都保持在停止前的状态,而当它被唤醒时,STM32使用HSI作为系统时钟(8MHz)运行,由于系统时钟会影响很多外设的工作状态,所以一般我们在唤醒后会重新开启HSE,把系统时钟设置回原来的状态。

38.1.4. 进入待机模式

类似地,STM32 HAL库也提供了控制进入待机模式的函数,其定义见。

代码清单 38‑3 进入待机模式

 /**
 * @brief 进入待机模式
 * @note 待机模式时,除了以下引脚,其余引脚都在高阻态:
 *          - 复位引脚
 *          - RTC_AF1 引脚 (PC13)(需要使能侵入检测、时间戳事件或RTC闹钟事件)
 *          - RTC_AF2 引脚 (PI8) (需要使能侵入检测或时间戳事件)
 *          - WKUP 引脚 (PA0) (需要使能WKUP唤醒功能)
 * @retval None
 */
 void HAL_PWR_EnterSTANDBYMode(void)
 {
     /* 选择待机模式 */
     PWR->CR1 |= PWR_CR1_PDDS;

     /* 设置内核寄存器的SLEEPDEEP位 */
     SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

     /* 存储操作完毕时才能进入待机模式,使用以下语句确保存储操作执行完毕 */
 #if defined ( __CC_ARM)
     __force_stores();
 #endif
     /* 等待中断唤醒 */
     __WFI();
 }

该函数中先配置了PDDS寄存器位及SLEEPDEEP寄存器位,接着调用__force_stores函数确保存储操作完毕后再调用WFI指令,从而进入待机模式。这里值得注意的是,待机模式也可以使用WFE指令进入的,如果您有需要可以自行修改。

在进入待机模式后,除了被使能了的用于唤醒的I/O,其余I/O都进入高阻态,而从待机模式唤醒后,相当于复位STM32芯片,程序重新从头开始执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值