这一节通过按键输入的实验,完成对IO口配置输入的学习,同时学习如何通过软件去抖动。这一节最终可以实现利用WK_UP按键控制LED亮灭的效果。
与上一节点亮LED相类似,这一节也需要在 HARDWARE
文件夹内新建文件 key.h
和 key.c
。同时将相应的文件加入到工程中。
查看原理图,获取WK_UP按键的相关信息。对应IO口 PA0
。高电平为有效电平,且没有外接下拉电阻。需要利用软件设置IO口为下拉状态。
GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
该函数可以获取到相应IO口的电平状态。
步骤:
#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) //WK_UP作为相应IO口状态读取的简写
//#define WK_UP PAin(0) 上一行代码与该行效果相同
void KEY_Init(void); //相应IO口配置初始化
u8 KEY_Scan(void); //WK_UP按键处理函数
#endif
#include "key.h"
#include "sys.h"
#include "delay.h"
void KEY_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能时钟
//IO口配置 由于是输入模式,所以不需要配置输出速度
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //WK_UP对应PA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //初始化 下拉
GPIO_Init(GPIOA, &GPIO_InitStructure); //用上述配置的结构体初始化
}
u8 KEY_Scan(void){ //按键检测
static char flag = 0; //默认WK_UP按键没有按下
if (WK_UP == 1){ //此时按键按下,可能是误触
delay_ms(10);
if (WK_UP == 1){ //延迟10ms,再次判断,可以排除误触的情况,称为“软件消抖”
flag = 1; //代表按键已经按过,但还未对其处理
}
}
if (WK_UP == 0 && flag == 1){ //此时上一次按键未处理,且上次按键已经释放
flag = 0; //复位flag
return 1; //主函数根据返回值的不同,进行不同的按键处理
}
return 0;
}
//以下是按键检测的另一种写法
//mode为1时,按键支持连按;为0时不支持连按
u8 KEY_Scan(u8 mode){
static u8 flag = 1;
if (mode) flag = 1; //mode为1时,进入检测函数时,flag就始终为1,即实现按键连按
if (flag && WK_UP){
delay_ms(10);
flag = 0; //flag复位,若mode为0,则下次检测不会再成功,即可阻止按键连按
if(WK_UP) return 1;
}else if(!WK_UP){ //若上次flag被复位,这次按键检测中将会对其置位,使得下次按键检测正常进行
flag = 1;
}
return 0; //未检测到按键按下,就会返回0
}
//此处省略头文件,之后一般都会省略头文件
int main(void){
delay_init();
LED_Init(); //LED相应IO口初始化
KEY_Init(); //按键相应IO口初始化
LED1 = 0; //点亮LED1
while(1){
u8 key = KEY_Scan(); //检测按键状态,返回值是1或0
if(key == 1){ //按键按下未处理
LED1 = !LED1; //点亮或熄灭LED1
}else{
delay_ms(10); //未检测到按键,进行下一次按键检测
}
}
}
至此,将程序烧写进单片机,就可以实现开篇提到的按键控制LED亮灭的功能了。这是不是非常的“阿美zing”呢?
main.c中的LED_Init()
相关配置代码可以参看之前的这篇文章:
\(\color{#0000FF}{STM32点亮LED(学习IO口配置输出)}\)
原文:https://www.cnblogs.com/Rane/p/13584874.html