很多单片机都有低功耗模式, STM32 也不例外。在系统或电源复位以后,微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码。当 CPU 不需继续运行时,可以利用多个低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。
#include "wkup.h"
//待命模式
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();
}
//检测 WKUP 脚的信号
//返回值 1:连续按下 3s 以上
// 返回值 0:错误的触发
u8 Check_WKUP(void)
{
u8 t=0;
LED0=0;
while(1)
{
if(WKUP_KD)
{
t++;
delay_ms(30);
if(t>=100)
{
LED0=0;
return 1;
}
}
else
{
LED0=1;
return 0;
}
}
}
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0);// 清除 LINE10 上的中断标志位
if(Check_WKUP())
{
Sys_Enter_Standby();
}
}
void WKUP_Init(void)
{
GPIO_InitTypeDef GPIO_ist;
NVIC_InitTypeDef NVIC_ist;
EXTI_InitTypeDef EXTI_ist;
//使能GPIOA和复用功能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
GPIO_ist.GPIO_Pin=GPIO_Pin_0;//PA0
GPIO_ist.GPIO_Mode =GPIO_Mode_IPD;//下拉输入
GPIO_Init(GPIOA,&GPIO_ist);
//中断线 0 连接 GPIOA.0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
EXTI_ist.EXTI_Line=EXTI_Line0;
EXTI_ist.EXTI_Mode= EXTI_Mode_Interrupt;
EXTI_ist.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_ist.EXTI_LineCmd= ENABLE;
EXTI_Init(&EXTI_ist);//初始化外部中断
NVIC_ist.NVIC_IRQChannel=EXTI0_IRQn;
NVIC_ist.NVIC_IRQChannelPreemptionPriority=2;
NVIC_ist.NVIC_IRQChannelSubPriority=2;
NVIC_ist.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_ist);
if(!Check_WKUP())Sys_Standby();
}
void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2RSTR |= RCC_APB2Periph;
}
else
{
RCC->APB2RSTR &= ~RCC_APB2Periph;
}
}
#ifndef _WKUP_H
#define _WKUP_H
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#define WKUP_KD PAin(0)//PA0 检测是否外部 WK_UP 按键按下
u8 Check_WKUP(void);//检测 WKUP 脚的信号
void WKUP_Init(void);//PA0 WKUP 唤醒初始化
void Sys_Enter_Standby(void);//系统进入待机模式
#endif
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "usmart.h"
#include "rtc.h"
#include "wkup.h"
void init(void)
{
NVIC_Configuration();
delay_init();
uart_init(9600);
LED_Init();
LCD_Init();
WKUP_Init();
usmart_dev.init(72);//初始化SMART组件
}
int main(void)
{
u8 t;
init();
POINT_COLOR=RED;
while(RTC_Init()) //RTC初始化 ,一定要初始化成功
{
LCD_ShowString(60,130,200,16,16,"RTC ERROR! ");
delay_ms(800);
LCD_ShowString(60,130,200,16,16,"RTC Trying...");
}
//显示时间
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(60,130,200,16,16," - - ");
LCD_ShowString(60,162,200,16,16," : : ");
while(1)
{
if(t!=calendar.sec)
{
t=calendar.sec;
LCD_ShowNum(60,130,calendar.w_year,4,16);
LCD_ShowNum(100,130,calendar.w_month,1,16);
LCD_ShowNum(124,130,calendar.w_date,2,16);
switch(calendar.week)
{
case 0:
LCD_ShowString(60,148,200,16,16,"Sunday ");
break;
case 1:
LCD_ShowString(60,148,200,16,16,"Monday ");
break;
case 2:
LCD_ShowString(60,148,200,16,16,"Tuesday ");
break;
case 3:
LCD_ShowString(60,148,200,16,16,"Wednesday");
break;
case 4:
LCD_ShowString(60,148,200,16,16,"Thursday ");
break;
case 5:
LCD_ShowString(60,148,200,16,16,"Friday ");
break;
case 6:
LCD_ShowString(60,148,200,16,16,"Saturday ");
break;
}
LCD_ShowNum(60,162,calendar.hour,2,16);
LCD_ShowNum(84,162,calendar.min,2,16);
LCD_ShowNum(108,162,calendar.sec,2,16);
LED0=!LED0;
}
delay_ms(10);
}
}