一、低功耗注意事项:
1、所有IO管脚,如果高阻状态端口是高电平,就设成上拉输入;如果高阻状态是低电平,设成下拉输入;如果高阻是中间状态,设成模拟输入。这个很多人都提到过,必须的。作为输出口就免了,待机你想输出个什么东西,一定要输,硬件上加上下拉就可以了
2、两个晶振输入脚要remap成普通IO,使用内部晶振
3、pwr的时钟要使能,即RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);这个也相当重要
4、关闭jtag口,并设成普通IO。
5、注意助焊膏的质量。
6、功耗计算方式:功耗=工作电压*工作电流
7、引脚电压的切换会对外部和内部电容负载产生动态损耗,其损耗与电压切换频率负载电容有关。
8、在配置IO模拟输入之前,一定不要锁定IO口。
二、低功耗模式
1、电源管理
为了方便进行电源管理,STM32把它的外设、内核等模块根据功能划分了供电区域(备份域电路、调压器供电电路、 ADC电源及参考电压),其内部电源区域划分见图1。
图 1 STM32供电图

① 备份域电路
STM32的LSE振荡器、RTC、备份寄存器及备份SRAM这些器件被包含进备份域电路中,这部分的电路可以通过STM32的VBAT引脚获取供电电源,在实际应用中一般会使用3V的钮扣电池对该引脚供电。当VDD主电源存在时,由于VDD电压较高,备份域电路通过VDD供电,当VDD掉电时,备份域电路由钮扣电池通过VBAT供电,保证电路能持续运行,从而可利用它保留关键数据。
② 调压器供电电路
在STM32的电源系统中调压器供电的电路是最主要的部分,调压器为备份域及待机电路以外的所有数字电路供电,其中包括内核、数字外设以及RAM,调压器的输出电压约为1.2V,因而使用调压器供电的这些电路区域被称为1.2V域
调压器可以运行在"运行模式"、"停止模式"以及"待机模式"。在运行模式下,1.2V域全功率运行;在停止模式下1.2V域运行在低功耗状态,1.2V区域的所有时钟都被关闭,相应的外设都停止了工作,但它会保留内核寄存器以及SRAM的内容;在待机模式下,整个1.2V域都断电,该区域的内核寄存器及SRAM内容都会丢失(备份区域的寄存器及SRAM不受影响)。
③ ADC电源及参考电压
为了提高转换精度,STM32的ADC配有独立的电源接口,方便进行单独的滤波。ADC的工作电源使用VDDA引脚输入,使用VSSA作为独立的地连接,VREF引脚则为ADC提供测量使用的参考电压。
2、低功耗模式
按功耗由高到低排列,STM32具有运行、睡眠、停止和待机四种工作模式。上电复位后STM32处于运行状态时,当内核不需要继续运行,就可以选择进入后面的三种低功耗模式降低功耗。三种低功耗模式见图2。


在这三种低功耗模式中,最低功耗的是待机模式,在此模式下,最低只需要2.2uA左右的电流。停止模式是次低功耗的,其典型的电流消耗在350uA左右。最后就是睡眠模式了。
功耗: 运行>睡眠>停止>待机
2.1、睡眠模式
在睡眠模式中,仅关闭了内核时钟,内核停止运行,但其片上外设、CM4核心的外设全都还照常运行。有两种方式进入睡眠模式,它的进入方式决定了从睡眠唤醒的方式,分别是WFI(wait for interrupt)和WFE(wait for event),即由等待"中断"唤醒和由"事件"唤醒。睡眠模式的各种特性见表1。

2.2、停止模式
在停止模式中,进一步关闭了其它所有的时钟,于是所有的外设都停止了工作,但由于其1.2V区域的部分电源没有关闭,还保留了内核的寄存器、内存的信息,所以从停止模式唤醒,并重新开启时钟后,还可以从上次停止处继续执行代码。停止模式可以由任意一个外部中断(EXTI)唤醒。在停止模式中可以选择电压调节器为开模式或低功耗模式,可选择内部FLASH工作在正常模式或掉电模式。停止模式的各种特性见表2。

2.3、待机模式
待机模式,它除了关闭所有的时钟,还把1.2V区域的电源也完全关闭了,也就是说,从待机模式唤醒后,由于没有之前代码的运行记录,只能对芯片复位,重新检测boot条件,从头开始执行程序。它有四种唤醒方式,分别是WKUP(PA0)引脚的上升沿,RTC闹钟事件,NRST引脚的复位和IWDG(独立看门狗)复位。待机模式的各种特性见表3。

注:在以上讲解的睡眠模式、停止模式及待机模式中,若备份域电源正常供电,备份域内的RTC都可以正常运行、备份域内的寄存器及备份域内的SRAM数据会被保存,不受功耗模式影响。
3、进入低功耗
void PWR_EnterSleepMode(uint8_t PWR_SLEEPEntry); //睡眠模式
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry); //停机模式
void PWR_EnterSTANDBYMode(void); //待机模式
图 3 进入各种低功耗模式时都需要调用WFI 或WFE 命令


3.1、睡眠模式
直接调用WFIWFE 指令可以进入睡眠模式。
a) 设置中断(Interrupt)或事件(Event)
/* 初始化按键为中断模式,按下中断后会进入中断服务函数 */
EXTI_Key_Config();
b) 进入睡眠
        __WFI(); //WFI 指令进入睡眠
c) 中断退出睡眠后,继续执行后面的程序
3.2、停止模式
进入停止模式后,STM32 的所有I/O都保持在停止前的状态,而当它被唤醒时,STM32 使用HSI 作为系统时钟(16MHz)运行,由于系统时钟会影响很多外设的工作状态,所以一般我们在唤醒后会重新开启HSE,把系统时钟设置会原来的状态。
a) 设置中断(Interrupt)或事件(Event)
/* 初始化按键为中断模式,按下中断后会进入中断服务函数 */
EXTI_Key_Config();
b) 进入睡眠
/*设置停止模式时,FLASH 进入掉电状态*/
PWR_FlashPowerDownCmd (ENABLE);
/* 进入停止模式,设置电压调节器为低功耗模式,等待中断唤醒 */
PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);
c) 中断退出睡眠后,继续执行后面的程序
d) 需要先恢复时钟
//获取刚被唤醒时的时钟状态
//时钟源
clock_source_wakeup = RCC_GetSYSCLKSource ();
//时钟频率
RCC_GetClocksFreq(&clock_status_wakeup);
//从停止模式下被唤醒后使用的是HSI 时钟,此处重启HSE 时钟,使用PLLCLK
SYSCLKConfig_STOP();
//获取重新配置后的时钟状态
//时钟源
clock_source_config = RCC_GetSYSCLKSource ();
//时钟频率
RCC_GetClocksFreq(&clock_status_config);
e) 正常执行后面的程序
3.3、待机模式
不需要中断,通过WKUP引脚的上升沿,RTC闹钟、唤醒、入侵、时间戳事件或NRST引脚外部复位及IWDG复位唤醒。
a) 进入睡眠
/*清除WU 状态位*/
PWR_ClearFlag (PWR_FLAG_WU);
/* 使能WKUP 引脚的唤醒功能 ,使能PA0*/
PWR_WakeUpPinCmd (ENABLE);
/* 进入待机模式 */
PWR_EnterSTANDBYMode();
b) 唤醒后,重新执行程序
e) 检测是否是唤醒后的程序
//检测复位来源
PWR_GetFlagStatus(PWR_FLAG_WU)