STM32_07_按键
按键介绍
硬件设计
- KEY_UP:
3.3V --- KEY_UP --- PA0 | CPU
KEY0:
GND --- KEY0 --- PE4 | CPU
KEY1:
GND --- KEY1 --- PE3 | CPU
KEY2:
GND --- KEY2 --- PE2 | CPU- 默认:断开状态 按下:导通状态
- 按下按键,完成某种功能
- 如何检测某个按键按下?
KEY_UP: 配置为下拉输入即可(接的是3.3V电源,因此按键按下默认高电平)
按键松开 - PA0 - 低电平
按键按下 - PA0 - 高电平
按键松开 - PA0 - 低电平
循环检测, 只要检测到高电平, 认为KEY_UP按下
KEY_0: 配置为上拉输入(接地,PE4->低电平,因此按键按下默认低电平)
按键松开 - PE4 - 高电平
按键按下 - PE4 - 低电平
按键松开 - PE4 - 高电平
后续只要检测到PE4低电平, 认为KEY0按下
实战演练-掌控需求
软件实现
代码示例:
key.h:
// key.h
#ifndef __KEY_H__
#define __KEY_H__#include "stm32f10x.h"
#include "system.h"// 位带操作// KEY0 - PE4
#define KEY0_PIN GPIO_Pin_4
#define KEY0_PORT GPIOE
#define KEY0 PEin(4) // 判断GPIOE4引脚的高低电平
#define KEY0_PRESS 1 // key0的键值extern void KEY_Init(void);
//
// 扫描是否有按键扫描
//
extern u8 KEY_Scan(void);
#endif
key.c:
// key.c
#include "key.h"
#include "systick.h" // 定时器
//
// 初始化函数
// GPIOE4:上拉输入(高电平 - 低电平 - 高电平)
//
void KEY_Init(void){// 1.打开GPIOE控制器的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);// 2.配置GPIOE4为上拉输入// 当我们把引脚配置成输入时,不用配置速率,寄存器里面是没有速率的GPIO_InitTypeDef GPIO_Config;GPIO_Config.GPIO_Pin = GPIO_Pin_4;GPIO_Config.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入GPIO_Init(KEY0_PORT, &GPIO_Config);}
//
// 扫描是否有按键按下 - 循环调用
// 如果按键按下,返回按键键值
// KEY0 - 1
// 否则返回0
//
u8 KEY_Scan(void){// key0 - 已经按下 - 不能再按了// = 0,没有按键被按下,可以按键了;=1, 按键已经被按下了,不能再按了static u8 ispressed = 0;if((ispressed == 0) && (KEY0 == 0)){delay_ms(10); // 加了这句代码就不会接触不良了// 如果if中的两个条件满足,此次确实按下了KEY0按键ispressed = 1;if(KEY0 == 0)// 如果是多个按键,你就不知道是哪个按键按下了,因此这里还要判断一次return KEY0_PRESS; // 返回KEY0键值}else if(KEY0 == 1){ // 没有按键按下ispressed = 0; // 标识这个按键松开了}return 0; // 没有按键按下
}
main.c:
// main.c
#include "stm32f10x.h"
#include "led.h"
#include "beep.h"
#include "system.h"
#include "systick.h"
#include "key.h"int main(void)
{// LED初始化 LED_Init();// BEEP初始化 BEEP_Init();// systick初始化 Systick_Init();// KEY初始化KEY_Init();// 定义变量获取扫描按键的返回值u8 key_value;while(1){key_value = KEY_Scan();switch(key_value){case KEY0_PRESS : LED0 = !LED0; break;}}
}
实验现象
按键抖动
delay_ms(10);
软件去抖
代码示例:
key.h:
// key.h
#ifndef __KEY_H__
#define __KEY_H__#include "stm32f10x.h"
#include "system.h"// 位带操作// KEY0 - PE4
#define KEY0_PIN GPIO_Pin_4
#define KEY0_PORT GPIOE
#define KEY0 PEin(4) // 判断GPIOE4引脚的高低电平
#define KEY0_PRESS 1 // key0的键值// KEY_UP - PA0 (低电平 - 高电平 - 低电平)
#define KEY_UP_PIN GPIO_Pin_0
#define KEY_UP_PORT GPIOA
#define KEY_UP PAin(0) // 判断PA0引脚的高低电平
#define KEY_UP_PRESS 2 // key0的键值// KEY1 - PE3
#define KEY1_PIN GPIO_Pin_3
#define KEY1_PORT GPIOE
#define KEY1 PEin(3) // 判断GPIOE4引脚的高低电平
#define KEY1_PRESS 3 // key0的键值// KEY2 - PE2
#define KEY2_PIN GPIO_Pin_2
#define KEY2_PORT GPIOE
#define KEY2 PEin(2) // 判断GPIOE4引脚的高低电平
#define KEY2_PRESS 4 // key0的键值extern void KEY_Init(void);
//
// 扫描是否有按键扫描
//
extern u8 KEY_Scan(void);
#endif
key.c:
// key.c
#include "key.h"
#include "systick.h" // 定时器
//
// 初始化函数
// GPIOE4:上拉输入(高电平 - 低电平 - 高电平)
// GPIOA0:下拉输入(低电平 - 高电平 - 低电平)
//
void KEY_Init(void){// 1.打开GPIOE控制器的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);// 1.2打开GPIOA控制器的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 2.配置GPIOE4为上拉输入// 当我们把引脚配置成输入时,不用配置速率,寄存器里面是没有速率的GPIO_InitTypeDef GPIO_Config;GPIO_Config.GPIO_Pin = GPIO_Pin_4;GPIO_Config.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入GPIO_Init(KEY0_PORT, &GPIO_Config); // 2.2配置GPIOA0为下拉输入GPIO_Config.GPIO_Pin = GPIO_Pin_0;GPIO_Config.GPIO_Mode = GPIO_Mode_IPD; // 下拉输入GPIO_Init(KEY_UP_PORT, &GPIO_Config);// 2.3配置GPIOE3为上拉输入GPIO_Config.GPIO_Pin = GPIO_Pin_3;GPIO_Config.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入GPIO_Init(KEY1_PORT, &GPIO_Config); }
//
// 扫描是否有按键按下 - 循环调用
// 如果按键按下,返回按键键值
// KEY0 - 1
// KEY_UP - 2
// KEY1 - 3
// 否则返回0
//
u8 KEY_Scan(void){// key0 - 已经按下 - 不能再按了// = 0,没有按键被按下,可以按键了;=1, 按键已经被按下了,不能再按了static u8 ispressed = 0;if((ispressed == 0) && ((KEY0 == 0) || (KEY_UP == 1) || (KEY1 == 0) || (KEY2 == 0))){delay_ms(10); // 加了这句代码就不会接触不良了// 如果if中的两个条件满足,此次确实按下了KEY0按键ispressed = 1;if(KEY0 == 0)// 如果是多个按键,你就不知道是哪个按键按下了,因此这里还要判断一次return KEY0_PRESS; // 返回KEY0键值else if(KEY_UP == 1)return KEY_UP_PRESS; // 返回KEY_UP键值else if(KEY1 == 0)return KEY1_PRESS;else if(KEY2 == 0)return KEY2_PRESS;}else if((KEY0 == 1) && (KEY_UP == 0) && (KEY1 == 1) && (KEY2 == 1)){ // 没有按键按下ispressed = 0; // 标识这个按键松开了}return 0; // 没有按键按下
}
main.c:
// main.c
#include "stm32f10x.h"
#include "led.h"
#include "beep.h"
#include "system.h"
#include "systick.h"
#include "key.h"int main(void)
{// LED初始化 LED_Init();// BEEP初始化 BEEP_Init();// systick初始化 Systick_Init();// KEY初始化KEY_Init();// 定义变量获取扫描按键的返回值u8 key_value;while(1){key_value = KEY_Scan();switch(key_value){case KEY0_PRESS : LED0 = !LED0; break;case KEY_UP_PRESS : BEEP = !BEEP; break;case KEY1_PRESS : LED1 = 0; break;case KEY2_PRESS : LED1 = 1; break;}}
}