很多单片机都有低功耗模式,STM32F4 也不例外。在系统或电源复位以后,微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码。当 CPU 不需继续运行时,可以利用多个低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。STM32F4 的 3 种低功耗模式我们在 5.2.4 节有粗略介绍,这里我们再回顾一下。
STM32F4 提供了 3 种低功耗模式,以达到不同层次的降低功耗的目的,这三种模式如下:
1)睡眠模式(CM4 内核停止工作,外设仍在运行);
2)停止模式(所有的时钟都停止);
3)待机模式;
用到的硬件资源有:
1) 指示灯 DS0
2) KEY_UP 按键
3) TFTLCD 模块
stm32f4xx_pwr.c / stm32f4xx_pwr.h
void PWR_EnterSTOPMode();//进入停机模式
void PWR_EnterSTANDBYMode(void);//进入待机模式
void PWR_WakeUpPinCmd(FunctionalState NewState);//使能Wakeup引脚唤醒
FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);
void PWR_ClearFlag(uint32_t PWR_FLAG);
core_cm4.h
__WFI();
__WFE();
按下KEY0进入待机模式 KEY_UP唤醒
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "usmart.h"
#include "lcd.h"
#include "rtc.h"
#include "rng.h"
#include "key.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168);
uart_init(115200);
usmart_dev.init(84);
LED_Init();
KEY_Init();
LCD_Init();
POINT_COLOR = RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"PWR TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@tom");
LCD_ShowString(30,110,200,16,16,"2020/09/10");
while(1)
{
if (Key_Scan() == KEY0_PRESS)
{
//使能PWR时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
//后备区域访问使能
PWR_BackupAccessCmd(ENABLE);
//关闭RTC相关中断
RTC_ITConfig(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA,DISABLE);
//清除RTC相关中断标志
RTC_ClearITPendingBit(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA);
//清除wake-up标志
PWR_ClearFlag(PWR_FLAG_WU);
//使能唤醒管脚功能
PWR_WakeUpPinCmd(ENABLE);
//进入待机模式
PWR_EnterSTANDBYMode();
}
delay_ms(10);
}
}
wkup.h
#ifndef __WK_UP_H__
#define __WK_UP_H__
#include "sys.h"
#define WKUP_KD PAin(0)
//检测WKUP脚的信号
u8 Check_WKUP(void);
//WKUP唤醒初始化
void WKUP_Init(void);
//系统进入待机模式
void Sys_Enter_Standby(void);
#endif/*__WK_UP_H__*/
wkup.c
#include "wkup.h"
#include "led.h"
#include "delay.h"
//检测WKUP脚的信号
u8 Check_WKUP(void)
{
u8 t = 0;
//记录松开的次数
u8 tx = 0;
LED1 = 0;
while(1)
{
if (WKUP_KD)
{
t++;
tx = 0;
}
else
{
tx++;
//查过90ms没有WKUP信号
if (tx > 3)
{
LED1 = 1;
return 0;
}
}
delay_ms(30);
if (t >= 100)
{
LED1 = 0;
return 1;
}
}
}
//WKUP唤醒初始化
void WKUP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//输入模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
//(检查是否是正常开)机
if(Check_WKUP()==0)
{
Sys_Enter_Standby(); //不是开机,进入待机模式
}
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//PA0 连接到中断线0
EXTI_InitStructure.EXTI_Line = EXTI_Line0;//LINE0
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
EXTI_Init(&EXTI_InitStructure);//配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
NVIC_Init(&NVIC_InitStructure);//配置NVIC
}
//系统进入待机模式
void Sys_Enter_Standby(void)
{
//等待按键松开
while(WKUP_KD)
;
//复位所有的IO口
RCC_AHB1PeriphResetCmd(0x04FF, ENABLE);
//使能PWR时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
//后备区域访问使能
PWR_BackupAccessCmd(ENABLE);
//关闭RTC相关中断
RTC_ITConfig(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA,DISABLE);
//清除RTC相关中断标志
RTC_ClearITPendingBit(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA);
//清除wake-up标志
PWR_ClearFlag(PWR_FLAG_WU);
//使能唤醒管脚功能
PWR_WakeUpPinCmd(ENABLE);
//进入待机模式
PWR_EnterSTANDBYMode();
}
//中断,检测到PA0脚的一个上升沿.
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE10上的中断标志位
if(Check_WKUP())//关机?
{
Sys_Enter_Standby(); //进入待机模式
}
}
main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "usmart.h"
#include "lcd.h"
#include "rtc.h"
#include "rng.h"
#include "key.h"
#include "wkup.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168);
uart_init(115200);
usmart_dev.init(84);
LED_Init();
KEY_Init();
LCD_Init();
WKUP_Init();
POINT_COLOR = RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"PWR TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@tom");
LCD_ShowString(30,110,200,16,16,"2020/09/10");
while(1)
{
LED2 = !LED2;
delay_ms(250);
}
}
6.1 【STM32】STM32系列教程汇总
网址:【STM32】STM32系列教程汇总
该教程参考了正点原子的《STM32 F4 开发指南》