KEY按键

KEY.h

#ifndef __KEY_
#define __KEY_
void KEY_Init(void);
uint8_t GET_KeyNum(void);
#endif

KEY.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
void KEY_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_InitStruct);
}
uint8_t GET_KeyNum(void)
{
	uint8_t KeyNum = 0;
	if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0);//如果按键一直处于按下状态,则卡在这里,直到松手才把按键状态返回
		Delay_ms(20);
		KeyNum = 1;
	}
	if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0);//如果按键一直处于按下状态,则卡在这里,直到松手才把按键状态返回
		Delay_ms(20);
		KeyNum = 2;
	}
	return KeyNum;
}

main.c

#include "stm32f10x.h"                  // Device header
#include "LED.h"
#include "KEY.h"
uint8_t KeyNum;
int main(void)
{

	LED0_Init();
	KEY_Init();
	while(1)
	{
		KeyNum = GET_KeyNum();
		if(KeyNum == 1){
			LED0_On();
		}
		if(KeyNum == 2){
			LED0_Off();
		}
	}
}

不推荐用EXTI中断触发按键事件:
按键的信号不是转瞬即逝的
不好处理按键抖动
推荐使用定时器中断

KEY按键_第1张图片
如果不消抖,CPU可能会误处理

怎么判断按键按下?
两种判定:
1、按下就处理(下降沿触发)
2、弹起才处理(上升沿触发)
下面介绍“按下就处理“(下降沿触发)的情况:
KEY按键_第2张图片
1)读取一次电平,只有检测到高电平,才继续处理
2)消抖20ms
3)在读取一次电平,若此时未低电平,才认为是一次按键事件。
对于可支持连按的模式(一次按键动作,无论停留多久,只算作一次按键事件),对于GPIO_ReadInputDataBit这一函数,我们只能知道当前电平高低,如读取到的是低电平,我们无法判断是

连按模式
KEY按键_第3张图片
如何在此基础上,修改代码,变为非连按模式?
首先,增加上次一按键状态检测机制,即只有当第一次读取按键状态为弹起时,防抖后,再当第二次读取时,为按下状态,才认为是一次按键事件。
1)定义一个参数:标记当前按键是否按下
2)按键标记为弹起且检测到按键高电平->防抖->按键标记为按下,再读取一次,若为低电平,则认为是一次按键事件。
其中,当已经进行过一次按键事件,但此时按键未松开,且主函数重新运行一次到该按键扫描函数,此时按键标记为按下,就算检测到高电平,也无法触发按键入口;
再一次,主函数再一次运行到扫描函数,此时按键已经松开,读取到的是高电平,重置按键标记为弹起;
以上,一次按键事件彻底结束。
KEY按键_第4张图片
其中,是否支持连续按,最重要的是按下标志位

KEY按键_第5张图片

你可能感兴趣的:(STM32,stm32)