cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断)
cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断)https://blog.csdn.net/qq_16255321/article/details/43086403很多单片机都有低功耗模式, STM32 也不例外。在系统或电源复位以后,微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码。当 CPU 不需继续运行时,可以利用多
cortex_m3_stm32嵌入式学习笔记(十五):待机唤醒实验(WK_UP外部中断)
https://blog.csdn.net/qq_16255321/article/details/43086403
很多单片机都有低功耗模式, STM32 也不例外。在系统或电源复位以后,微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码。当 CPU 不需继续运行时,可以利用多个低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。
STM32 的低功耗模式有 3 种:
1)睡眠模式( CM3 内核停止,外设仍然运行)
2)停止模式(所有时钟都停止)
3)待机模式( 1.8V 内核电源关闭)

在这三种低功耗模式中,最低功耗的是待机模式,在此模式下,最低只需要 2uA 左右的电流。停机模式是次低功耗的,其典型的电流消耗在 20uA 左右。最后就是睡眠模式了。用户可以根据自己的需求来决定使用哪种低功耗模式。
本节实验是待机模式的实验,根据上表可以看到有4种方式进入待机模式,我们选择第一种,即通过WK_UP的外部中断来触发进入待机模式的方式
配置步骤:
1)使能电源时钟。
2) 设置 WK_UP 引脚作为唤醒源。
3)设置 SLEEPDEEP 位,设置 PDDS 位,执行 WFI 指令,进入待机模式。
4)最后编写 WK_UP 中断函数。
wkup.c
-
#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(); -
}
可以看到我们设定的是3秒有效,即按下WK_UP键3秒以上才会进入待机模式(关机)然后再按3秒以上便会开机。
可能对开机有点不大理解 我们找到关机函数中复位IO口那个函数源码
-
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; -
} -
}
因为我们传进去的第二个参数是DISABLE 所以它会执行 RCC->APB2RSTR &= ~RCC_APB2Periph;
可以看到每次都对 APB2Periph取反后按位与, 达到开关机的效果。。
wkup.h
-
#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
主函数直接保留上一节时钟的代码(加了WKUP的初始化)。。在LCD上显示时间,按WP_UP3秒关机
-
#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); -
} -
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)