背景
1、传统的按键检测使用阻塞式延迟去抖动,容易造成CPU浪费。
2、对于输入动作容易造成重复,引发混乱(假设我按住一个按钮,得到了111111111111111111111111111的结果)
因此,我们引入通过检测跳变来间接检测输入按键的检测。
原理很简单:
1、初始化一个flag,给定默认值。
2、按下按钮以后,电平发生变化,同时让flag置到某个状态。
3、在还没松开按键之前,系统将定期检测(检测间隔大于抖动时间,所以不用额外去抖动),由于flag并不满足条件,所以不执行任何动作
4、松开以后,flag置为默认值,执行按键响应代码,结束。
代码为:
(STM32F4xx HAL库版本)
#include "sys.h"
#include "usart.h"
#define KEY0 PAin(0) //KEY0按键PA0
u8 KEY_Scan(u8 mode) // 可拓展以支持多键检测
{
/*
mode: 扫描模式
0:跳变模式 :仅在“低-高”时有效
1:连按模式 :长按多久便多久有效
返回值:
0 :表示没有按键按下(即读取无效)
非0:用户自定义,不同的返回值可以是不同的键值
*/
static u8 key_up = 1; //按键松开标志(模式0使用)
if(mode == 1) key_up = 1; // 支持连按
if(key_up && (KEY0 == 0 /* 逻辑 “或 xx==0” 拓展区 ,可获取其他的IO*/))
{
key_up = 0;
if(KEY0 == 0) return 1; // 键值1
/* 键值有效返回区 ,可获取其他的IO*/
// if(KEY1 == 0) return 2; // 键值2
}else if(KEY0 == 1/* 逻辑 “且 xx==1” 拓展区 ,*/) key_up = 1;
return 0; //无按键按下
}
// 跳变式检测按钮是否输入
int main(void)
{
int key = -1;
int flag = 0;
GPIO_InitTypeDef GPIO_Initure;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,8,2,8); //设置时钟,180Mhz
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
__HAL_RCC_GPIOG_CLK_ENABLE(); //开启GPIOG时钟
GPIO_Initure.Pin = GPIO_PIN_0;
GPIO_Initure.Mode = GPIO_MODE_INPUT;
GPIO_Initure.Pull = GPIO_NOPULL;
GPIO_Initure.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
GPIO_Initure.Pin = GPIO_PIN_13|GPIO_PIN_14;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull = GPIO_NOPULL;
GPIO_Initure.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOG,&GPIO_Initure);
while(1)
{
// 这一段代码是为了直观地看出按钮按下去的情况:按下亮灯,否则灭灯
key = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
if(key == 1)
{
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_14,GPIO_PIN_SET);
}else
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_14,GPIO_PIN_RESET);
// 跳变式检测按钮是否输入的代码:当有低-高的电平跳变时,对灯状态取反
key = KEY_Scan(1);
if(key!=0)
{
flag = ~flag;
if(flag == 0)
{
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_13,GPIO_PIN_SET);
}else
{
HAL_GPIO_WritePin(GPIOG,GPIO_PIN_13,GPIO_PIN_RESET);
}
Delay_ms(10);
}
}
}
© 著作权归作者所有
举报
发表评论
0/200