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芯片,程序重新从头开始执行。

6191

被折叠的 条评论
为什么被折叠?



