初学者分享,各位大佬指正!!
项目:stm32f103c8t6待机模式与唤醒
现象:
正常模式:按下PB5,实现控制PA1小灯(非开关小灯);
待机模式:按下PA0 3s,实现待机,PA1小灯灭;
唤醒:按一下PA0,恢复到正常模式;
接线图:
1.待机模式/唤醒说明:
1.1 待机条件:
1.当进入睡眠模式时,使能外部的SLEEPDEEP信号,以允许停止系统时钟。
2.电源控制寄存器(PWR_CR)中PDDS位,设置为1。
3.电源控制/状态寄存器(PWR_CSR) 中EWUP位,设置为1。
1.2 唤醒条件(4选1):
条件:WKUP引脚的上升沿(给PA0一个高电平)(选择这一个)
2. 代码:
四个.c文件,直接复制就能跑(按照上图接好线)
2.1 Standby.c
#include "stm32f10x.h"
#include "Standby.h"
#include "Delay.h"
#include "LED.h"
/* 按下PB5按键 正常点亮关闭小灯PA1,长按3sPA0进入待机模式,小灯熄灭,按一下PA0唤醒*/
//待机模式
void Sys_Standby(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能PWR外设时钟
PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能,在WkUp的上升沿进行
PWR_EnterSTANDBYMode(); //进入待机(STANDBY)模式 设置相应的进入条件(已经封装成了完整的函数)
}
//系统进入待机模式
//1.复位所有的io
//2.待机模式设置
void Sys_Enter_Standby(void)
{
RCC_APB2PeriphResetCmd(0x01fc,DISABLE);//复位
Sys_Standby();//启动待机模式
}
//检测WKUP脚的信号
u8 Check_WKUP(void)
{
uint16_t t=0; //记录按下的时间
while(1)
{
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))//判断按下的时间
{
t++; //已经按下了
Delay_ms(30);
if(t>=100) //按下超过3秒钟
{
return 1; //按下3s以上了
}
}
else
{
return 0;
}
}
}
//中断
void EXTI9_5_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line5); // 清除中断标志位
if (Check_WKUP()) // 检查按键是否长按3秒
{
Sys_Enter_Standby(); // 进入待机模式
}
}
//PA0 WKUP唤醒初始化
void WKUP_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);//使能GPIOA和复用功能时钟
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//使用外部中断方式
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //中断线0连接GPIOA.0
EXTI_InitStructure.EXTI_Line = EXTI_Line0; //设置按键所有的外部线路
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设外外部中断模式:EXTI线路为中断请求
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); // 初始化外部中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级2级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
// if(Check_WKUP()) Sys_Standby(); //按键未按下或按下时间不足 3 秒,进入待机模式
}
2.2 main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Key.h"
#include "LED.h"
#include "Standby.h"
uint8_t Key = 0;
int main(void)
{
GPIO_Config();
LED_Init();
WKUP_Init();
while (1)
{
Key = Key_GetNum();
if (Key == 1)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_SET);
Delay_ms(100);
Key = 0;
}
GPIO_WriteBit(GPIOA, GPIO_Pin_1,Bit_RESET);
}
}
2.3 LED.c
#include "stm32f10x.h" // Device header
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
2.4 Key.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
// 初始化GPIO
void GPIO_Config(void)
{
// 使能GPIOA和GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
// 配置PB5为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
uint8_t Key_GetNum(void)
{
uint8_t Keyum = 0;
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5) == 0)
{
Delay_ms(20);
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5) == 0);
Delay_ms(20);
Keyum = 1;
}
return Keyum;
}
参考: