1.STM32待机模式介绍
很多单片机具有低功耗模式,比如MSP430、STM8L等,我们的STM32也不例外。默认情况下,系统复位或上电复位后,微控制器进入运行模式。在运行模式下,HCLK 为CPU提供时钟,并执行程序代码。这是正常的一般运行模式。
而当 CPU 不需继续运行(例如等待外部事件)时,可以利用多种低功耗模式来节省功耗。用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。
当然在运行模式下,也可以通过如下方式降低功耗:
(1)降低系统时钟速度
(2)不使用 APBx 和 AHB 外设时,将对应的外设时钟关闭
STM32 提供了 3 种低功耗模式,以达到不同层次的降低功耗的目的,这三种模式如下:
(1)睡眠模式( CM3 内核停止工作,外设仍在运行)
(2)停止模式(所有时钟都停止)
(3)待机模式( 1.8 V 内核电源关闭)
这三种模式所需的功耗是逐级递减,也就是说待机模式功耗是最低的。三种低功耗模式汇总表如图所示:
本章我们仅对STM32的待机模式进行介绍,其他2种模式可以参考《STM32F10x中文参考手册》-4电源控制器(PWR)章节,里面有详细的介绍。
在睡眠模式中,仅关闭了内核时钟,内核停止运行,但其片上外设, CM3 核心的外设全都照常运行。
在停止模式中,进一步关闭了其它所有的时钟,于是所有的外设都停止了工作,但由于其 1.8V 区域的部分电源没有关闭,还保留了内核的寄存器、内存的信息,所以从停止模式唤醒,并重新开启时钟后,还可以从上次停止处继续执行代码。
在待机模式中,它除了关闭所有的时钟,还把 1.8V 区域的电源也完全关闭了,也就是说,从待机模式唤醒后,由于没有之前代码的运行记录,只能对芯片复位,重新检测BOOT条件,从头开始执行程序。
那么我们如何进入待机模式呢?其实很简单,只要按下图所示的步骤执行就可以了。
从待机模式唤醒后,程序将按照复位(启动引脚采样、复位向量已获取等)后的方式重新执行。电源控制/状态寄存器(PWR_CSR)将会指示内核由待机状态退出。
在进入待机模式后,除了复位引脚以及被设置为防侵入或校准输出时的 TAMPER (PC13)引脚和被使能的唤醒引脚( WK_UP 脚(PA0)),其他的 IO 引脚都将处于高阻态。
2.待机模式配置步骤
接下来我们介绍下如何使用库函数进入和退出待机模式。这个也是在编写程序中必须要了解的。具体步骤如下:(电源管理相关库函数在stm32f10x_pwr.c和stm32f10x_pwr.h文件中)
(1)使能电源时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
(2)设置WK_UP引脚为唤醒源
PWR_WakeUpPinCmd(ENABLE);
(3)进入待机模式
PWR_EnterSTANDBYMode();//进入待机模式
PWR_ClearFlag(PWR_FLAG_WU);//清除Wake-up 标志
3.硬件电路
本实验使用到硬件资源如下:
(1)D1指示灯
(2)串口1
(3)K_UP按键
D1指示灯用来提示系统正常运行,K_UP按键用来唤醒待机模式,串口1用来输出提示信息。
4.编写待机唤醒程序
本实验所要实现的功能是:系统运行时D1指示灯闪烁,5秒后进入待机模式,D1指示灯熄灭,同时串口printf输出相关提示信息,通过K_UP按键实现唤醒。程序框架如下:
(1)配置进入与退出待机模式
(2)编写主函数
main.c
#include "system.h"
#include "led.h"
#include "SysTick.h"
#include "usart.h"
#include "input.h"
#include "wakeup.h"
int main()
{
u8 i;
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
LED_Init();
USART1_Init(9600);
while(1)
{
for (i=9;i>0;i--)
{
printf("time:=%d\r\n",i);
led1=!led1;
delay_ms(1000);
}
printf("进入待机模式\r\n");
delay_ms(1000);
Enter_StandbyMode();
}
}
wakeup.c
#include "wakeup.h"
void Enter_StandbyMode()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//1)使能电源时钟
PWR_WakeUpPinCmd(ENABLE);//(2)设置WK_UP引脚为唤醒源
PWR_ClearFlag(PWR_FLAG_WU);//清除Wake-up 标志
PWR_EnterSTANDBYMode();//进入待机模式
}
wakeup.h
#ifndef _wakeup_H
#define _wakeup_H
#include "system.h"
void Enter_StandbyMode(void);
#endif
以上程序烧录到开发板上测试,结果如下。实验是成功的。