【STM32】待机唤醒程序示例

00. 目录

01. 待机模式简介

很多单片机都有低功耗模式,STM32F4 也不例外。在系统或电源复位以后,微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码。当 CPU 不需继续运行时,可以利用多个低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。STM32F4 的 3 种低功耗模式我们在 5.2.4 节有粗略介绍,这里我们再回顾一下。
STM32F4 提供了 3 种低功耗模式,以达到不同层次的降低功耗的目的,这三种模式如下:
1)睡眠模式(CM4 内核停止工作,外设仍在运行);
2)停止模式(所有的时钟都停止);
3)待机模式;

02. 硬件模块

用到的硬件资源有:
1) 指示灯 DS0
2) KEY_UP 按键
3) TFTLCD 模块

03. 相关函数

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();

04. 程序示例一

按下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);
	}
}

05. 程序示例二

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);
	}
}

06. 附录

6.1 【STM32】STM32系列教程汇总

网址:【STM32】STM32系列教程汇总

07. 声明

该教程参考了正点原子的《STM32 F4 开发指南》

猜你喜欢

转载自blog.csdn.net/dengjin20104042056/article/details/108517208
今日推荐