一、背景
最近接触到了stm32低功耗模式,这个内容自己不是很熟悉,因为低功耗平时接触比较少。于是打算自学一下stm32低功耗部分,记录一下自己的学习过程,分享给有需要的人。
以下了解和学习基于正点原子战舰V3开发板,核心是STM32F103ZET6
二、计划
先了解相对应知识,然后通过代码实现验证,文末会根据情况放上我的代码供大家参考。
三、基础知识
STM32低功耗模式一共有三种,分别是:睡眠模式、停止模式、待机模式
(1)睡眠模式:该模式下内核会关闭,但外设继续工作;
(2)停止模式:该模式下所有时钟关闭,SARM保留;
(3)待机模式:该模式下1.8v内核供电停止,SARM清空,寄存器内容丢失,只有备份的寄存器和待机电路维持供电,再次唤醒有点类似复位重启。
当然我们在不进入这三种模式的情况下,也有降低功耗的方法,这里我提供两条:
①、降低系统时钟;
②、关闭APB和AHB总线上未被使用的外设时钟。
在我们简单了解这三种模式之后,下面是我们如何进入这三种模式,以及唤醒方式。
注意:
(1)、睡眠模式下CPU时钟关,对其他时钟和ADC时钟无影响;
(2)、停止模式、待机模式关闭所有1.8V区域时钟。
(3)、待机模式下所有i/O引脚都会处于高阻态,除了复位引脚、被使能的唤醒引脚、TAMPER引脚
(4)相应函数
stm32固件库中低功耗操作函数:stm32f10x_pwr.c / stm32f10x_pwr.h
void PWR_WakeUpPinCmd(FunctionalState NewState);
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);
void PWR_EnterSTANDBYMode(void);
这三个函数是从stm32f10x_pwr.h文件中复制出来的,这三个函数对于低功耗的配置非常重要,我这里会将自己对这三个函数的理解写下来。
(1)、void PWR_WakeUpPinCmd(FunctionalState NewState);
这是一个WK_UP引脚使能的配置函数,我们跳转查看它的本体是一个位操作:
void PWR_WakeUpPinCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CSR_EWUP_BB = (uint32_t)NewState;
}
通过这个函数内容的描述我们发现EWUP,这个就是PWR_CSR电源控制/状态寄存器的位8。
查询相关资料这个位的使能方式如下:
- 0:WKUP引脚为通用I\O。WKUP引脚上的时间是不能用于CPU的唤醒
- 1:WKUP引脚用于将CPU从待机模式唤醒,WKUP引脚被设置为下拉的配置,系统复位时将进行清除
(2)、void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);
这是一个进入到停止模式的函数
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;
tmpreg &= CR_DS_MASK;
tmpreg |= PWR_Regulator;
PWR->CR = tmpreg;
SCB->SCR |= SCB_SCR_SLEEPDEEP;
if(PWR_STOPEntry == PWR_STOPEntry_WFI)
{
__WFI();
}
else
{
__WFE();
}
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
}
(3)、void PWR_EnterSTANDBYMode(void);
这个函数我们跳转查看一下它的本体,如下:
void PWR_EnterSTANDBYMode(void)
{
/* Clear Wake-up flag */
PWR->CR |= PWR_CR_CWUF;
/* Select STANDBY mode */
PWR->CR |= PWR_CR_PDDS;
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM )
__force_stores();
#endif
/* Request Wait For Interrupt */
__WFI();
}
分割线---------------------------------------2022年3月11日
四、待机模式
今天是2022年3月13日,我们先着重研究一下STM32的待机模式。
经过上面的简单知识了解,我们知道唤醒待机模式有四种方式分别是:一个外部复位(NRST引脚)、IWDG复位、WKUP复位引脚上的上升沿或RTC闹钟事件发生时。
经过上图对进入待机模式方式的归纳,其中涉及到两个寄存器,分别是电源控制寄存器(PWR_CR)和电源控制/状态寄存器(PWR_CSR)。
这里我在研究的时候参考了这个博客:stm32学习笔记 PWR_xyzBlog-CSDN博客_单片机pwr
下图是电源控制器PWWR_CR 各位描述:
通过上图很清楚了,我们通过操作PDDS位使CPU进入待机模式,同时通过CWUF位清除之前的唤醒位。
(1)、待机模式具体配置步骤如下:
1、使能电源时钟
2、设置WK_UP引脚为唤醒源
3、设置SLEEPDEEP位、设置PDDS位、执行WFI指令,进入待机模式
4、编写WK_UP中断函数
(2)、软件设计
void Sys_Standby(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能PWR外设时钟
PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能
PWR_EnterSTANDBYMode(); //进入待命(STANDBY)模式
}
void Sys_Enter_Standby(void)
{
RCC_APB2PeriphResetCmd(0X01FC,DISABLE); //复位所有IO口
Sys_Standby();
}