STM32按键输入操作详解
一、硬件设计
按键KEY_UP连接带芯片的PA0引脚上,KEY_UP按键另一端是接在3.3V上,按下时输入到芯片管脚即为高电平。
按键KEY0、KEY1、KEY2分别连接在芯片的PE4、PE3、PE2引脚上
KEY0、KEY1、KEY2按键另一端是全部接在GND上,按下时输入到芯片管脚即为低电平
结论:只需轮询检测各个引脚的高低电平状态来判断按键是否有操作
KEY_UP – 下拉输入
默认低电平 — 高电平 — 低电平
KEY0/1/2 – 上拉输入
默认高电平 — 低电平 — 高电平
二、按键抖动
由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。
按键消抖就是先读取按键的状态,如果得到按键按下之后,延时10ms,再次读取按键状态,如果按键还是按下状态,那么说明按键已经按下。其中延时10ms就是软件消抖处理。
三、函数实现
按键点灯
//key.h
#ifndef _KEY_H
#define _KEY_H
#include "stm32f10x.h"
#include "system.h"
#define KEY0_PIN GPIO_Pin_4 //key0引脚
#define KEY1_PIN GPIO_Pin_3 //key1
#define KEY2_PIN GPIO_Pin_2 //key2
#define KEYUP_PIN GPIO_Pin_0//keyup
#define KEY_PORT GPIOE//KEY0按键引脚属于E组
#define KEYUP_PORT GPIOA
#define KEY0 PEin(4)//KEY0 - GPIOE4 - 引脚高低电平由外设控制
#define KEY1 PEin(3)
#define KEY2 PEin(2)
#define KEYUP PAin(0)
#define KEY0_PRESS 1//KEY0按键的键值
#define KEY1_PRESS 2
#define KEY2_PRESS 3
#define KEYUP_PRESS 4
extern void KEY_Init(void);//初始化函数
extern u8 KEY_Scan(void);//扫描,判断按键是否按下
#endif
//exti.c
#include "exti.h"
#include "led.h"
#include "beep.h"
#include "systick.h"
#include "key.h"
void My_Exti_Init(void){
//定义EXTI结构体,用于配置EXTI控制器
EXTI_InitTypeDef EXTI_Config;
NVIC_InitTypeDef NVIC_Config;
//使能AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//将KEY0按键的引脚GPIOE4映射到EXTI4中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
//配置EXTI工作参数
EXTI_Config.EXTI_Line = EXTI_Line4|EXTI_Line3;
EXTI_Config.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_Config.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Config.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_Config);
EXTI_Config.EXTI_Line = EXTI_Line0;
EXTI_Config.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_Config.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Config.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_Config);
//配置NVIC工作参数
NVIC_Config.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_Config.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_Config.NVIC_IRQChannelSubPriority = 0;
NVIC_Config.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_Config);
NVIC_Config.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_Config.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_Config.NVIC_IRQChannelSubPriority = 1;
NVIC_Config.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_Config);
NVIC_Config.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_Config.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_Config.NVIC_IRQChannelSubPriority = 2;
NVIC_Config.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_Config);
}
//自定义EXTI4中断处理函数 - 按键控制LED2开关
void EXTI4_IRQHandler(void){
//判断是否由EXTI4触发中断
if(EXTI_GetITStatus(EXTI_Line4) == SET){
delay_ms(10);
if(KEY0==0)
LED2=!LED2;
}
//清除中断到来标志位,否则一直有中断
EXTI_ClearITPendingBit(EXTI_Line4);
}
void EXTI3_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line3) == SET){
delay_ms(10);
if(KEY1==0)
BEEP_On();
}
//清除中断到来标志位,否则一直有中断
EXTI_ClearITPendingBit(EXTI_Line3);
}
void EXTI0_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line0) == SET){
delay_ms(10);
if(KEYUP==1)
BEEP_Off();
}
//清除中断到来标志位,否则一直有中断
EXTI_ClearITPendingBit(EXTI_Line0);
}
#include "key.h"
#include "systick.h"
void KEY_Init(void){
GPIO_InitTypeDef GPIO_Config;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_Config.GPIO_Pin = KEY0_PIN|KEY1_PIN|KEY2_PIN;
GPIO_Config.GPIO_Mode = GPIO_Mode_IPU;
//GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(KEY_PORT,&GPIO_Config);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_Config.GPIO_Pin = KEYUP_PIN;
GPIO_Config.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(KEYUP_PORT,&GPIO_Config);
}
//定义按键扫描函数
u8 KEY_Scan(void){
//ispressed=0按键没按下
//ispressed=1按键按下
static u8 ispressed = 0;
if(((KEY0==0)||(KEYUP==1)||(KEY1==0)||(KEY2==0))&&(ispressed==0)){
delay_ms(10);//消除抖动
ispressed=1;
if(KEY0==0)
return KEY0_PRESS;//返回KEY0按键的键值1
else if(KEY1==0)
return KEY1_PRESS;
else if(KEY2==0)
return KEY2_PRESS;
else if(KEYUP==1)
return KEYUP_PRESS;
}else if(KEY0==1||KEY1==1||KEY2==1||KEYUP==0){//表示按键松开
ispressed=0;
}
return 0;
}
作者:春析