这个滞回电压,是为了让单片机容忍一定程度的电压波动,而不是只要电压稍微一变化,就立刻掉电复位。
为了方便进行电源管理,STM32 把它的外设、内核等模块跟据功能划分了供电区域,其内部电源区域划分如图:
CPU内核为1.8V供电,以降低功耗,整个1.8V供电区域由电压调节器单独供电,有时CPU可以休眠,有时可以不休眠,这是由电压调节器来提供的。
stm32功耗模式
按功耗由高到低排列,STM32 具有运行、睡眠、停止和待机四种工作模式。上电复位后 STM32处于运行状态时,当内核不需要继续运行,就可以选择进入后面的三种低功耗模式降低功耗,这三种模式中,电源消耗不同、唤醒时间不同、唤醒源不同,用户需要根据应用需求,选择最佳的低功耗模式。三种低功耗的模式说明见下表。
睡眠模式下,任何中断都可以唤醒内核,外部 / 内部高速时钟保持打开,调压器保持打开,因此,内核只要被唤醒,就能马上正常的执行程序(优点:响应速度快;缺点:功耗比较大);
停止模式下,HSE和HSI被关闭,调压器可选开启或低功耗模式(若选为低功耗模式,则还需要加上调压器从低功耗切换至正常模式下的时间),外部中断唤醒内核。当内核被唤醒时,需要重新配置系统时钟使用外部 HSE 且 PLL 正常倍频(System_Init函数),这个过程就会消耗一定时间;否则程序会直接使用 HSI(不倍频) = 8MHz 作为系统时钟,此时系统运行的相当慢,一些对时钟要求较高的函数配置会无法运行(优点:功耗较小;缺点:需要重新配置系统时钟,响应速度慢);
待机模式下,整个1.8V供电区域被关闭,调压器被关闭,只能特定方式唤醒。唤醒之后程序从最开始(启动文件)执行(优点:功耗最低;缺点,每次都是复位执行);
3种模式的详细描述和寄存器配置
内核寄存器配置说明如下:
关于立即睡眠和退出后睡眠的区别(中文参考手册):
开启后会默认使用HSI作为系统时钟,通常我们为确保正常使用,还要重新开启HSE:
相关的寄存器配置:
电源控制寄存器,配置停止模式(正常 or 低功耗):
相关的寄存器配置:
电源管理库函数
1 配置PVD检测函数 PWR_PVDLevelConfig ,其实就是写入PWR_CR寄存器的这几位:
标准库函数源码:
/**
* @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD).
* @param PWR_PVDLevel: specifies the PVD detection level
* This parameter can be one of the following values:
* @arg PWR_PVDLevel_2V2: PVD detection level set to 2.2V
* @arg PWR_PVDLevel_2V3: PVD detection level set to 2.3V
* @arg PWR_PVDLevel_2V4: PVD detection level set to 2.4V
* @arg PWR_PVDLevel_2V5: PVD detection level set to 2.5V
* @arg PWR_PVDLevel_2V6: PVD detection level set to 2.6V
* @arg PWR_PVDLevel_2V7: PVD detection level set to 2.7V
* @arg PWR_PVDLevel_2V8: PVD detection level set to 2.8V
* @arg PWR_PVDLevel_2V9: PVD detection level set to 2.9V
* @retval None
*/
void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel));
tmpreg = PWR->CR;
/* Clear PLS[7:5] bits */
tmpreg &= CR_PLS_MASK;
/* Set PLS[7:5] bits according to PWR_PVDLevel value */
tmpreg |= PWR_PVDLevel;
/* Store the new value */
PWR->CR = tmpreg;
}
2 WFI 与 WFE 命令:
/* ################### Compiler specific Intrinsics ########################### */
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#define __enable_fault_irq __enable_fiq
#define __disable_fault_irq __disable_fiq
#define __NOP __nop
#define __WFI __wfi
#define __WFE __wfe
#define __SEV __sev
#define __ISB() __isb(0)
#define __DSB() __dsb(0)
#define __DMB() __dmb(0)
#define __REV __rev
#define __RBIT __rbit
#define __LDREXB(ptr) ((unsigned char ) __ldrex(ptr))
#define __LDREXH(ptr) ((unsigned short) __ldrex(ptr))
#define __LDREXW(ptr) ((unsigned int ) __ldrex(ptr))
#define __STREXB(value, ptr) __strex(value, ptr)
#define __STREXH(value, ptr) __strex(value, ptr)
#define __STREXW(value, ptr) __strex(value, ptr)
3 进入停止模式
配置PWR_CR寄存器的这两个位,以及SLEEPDEEP位。
/**
* @brief 进入停止模式
*
* @note 在停止模式下所有 I/O 的会保持在停止前的状态
* @note 从停止模式唤醒后,会使用 HSI 作为时钟源
* @note 调压器若工作在低功耗模式,可减少功耗,但唤醒时会增加延迟
* @param PWR_Regulator: 设置停止模式时调压器的工作模式
* @arg PWR_MainRegulator_ON: 调压器正常运行
* @arg PWR_Regulator_LowPower: 调压器低功耗运行
* @param PWR_STOPEntry: 设置使用 WFI 还是 WFE 进入停止模式
* @arg PWR_STOPEntry_WFI: WFI 进入停止模式
* @arg PWR_STOPEntry_WFE: WFE 进入停止模式
* @retval None
*/
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
uint32_t tmpreg = 0;
/* 检查参数 */
assert_param(IS_PWR_REGULATOR(PWR_Regulator));
assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
/* 设置调压器的模式 ------------*/
tmpreg = PWR->CR;
/* 清除 PDDS 及 LPDS 位 */
tmpreg &= CR_DS_MASK;
/* 根据 PWR_Regulator 的值(调压器工作模式)配置 LPDS,MRLVDS 及 LPLVDS 位*/
tmpreg |= PWR_Regulator;
/* 写入参数值到寄存器 */
PWR->CR = tmpreg;
/* 设置内核寄存器的 SLEEPDEEP 位 */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* 设置进入停止模式的方式-----------------*/
if (PWR_STOPEntry == PWR_STOPEntry_WFI) {
/* 需要中断唤醒 */
__WFI();
} else {
/* 需要事件唤醒 */
__WFE();
}
/* 以下的程序是当重新唤醒时才执行的,清除 SLEEPDEEP 位的状态 */
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
}
在执行最后一句代码前,系统由于调用了__WFI 或 __WFE,已经进入了停止模式,因此,这句清除SLEEPDEEP 位并不会执行。而当内核重新被唤醒时,才会清除SLEEPDEEP位,方便使用。
文章来源:https://www.toymoban.com/news/detail-830919.html
4 进入待机模式文章来源地址https://www.toymoban.com/news/detail-830919.html
/**
* @brief 进入待机模式
* @note 待机模式时,除以下引脚,其余引脚都在高阻态:
* -复位引脚
* - RTC_AF1 引脚 (PC13) (需要使能侵入检测、时间戳事件或 RTC 闹钟事件)
* - RTC_AF2 引脚 (PI8) (需要使能侵入检测或时间戳事件)
* - WKUP 引脚 (PA0) (需要使能 WKUP 唤醒功能)
* @note 在调用本函数前还需要清除 WUF 寄存器位
* @param None
* @retval None
*/
void PWR_EnterSTANDBYMode(void)
{
/* 清除 Wake-up 标志 */
PWR->CR |= PWR_CR_CWUF;
/* 选择待机模式 */
PWR->CR |= PWR_CR_PDDS;
/* 设置内核寄存器的 SLEEPDEEP 位 */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* 存储操作完毕时才能进入待机模式,使用以下语句确保存储操作执行完毕 */
#if defined ( __CC_ARM )
__force_stores();
#endif
/* 等待中断唤醒 */
__WFI();
}
到了这里,关于stm32专题三十一:电源管理实现低功耗的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!