提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
在使用STM32或其他单片机开发项目时,经常需要用到独立按键进行控制。
通常一个独立按键需要使用一个IO口,如果项目需要按键实现多个功能,往往需要使用到多个按键,需要使用到多个IO口。在IO口资源紧张或不希望使用太多按键时。可以使用以下方法实现一个按键单击,双击,长按返回不同键值的功能,从而减少独立按键的使用。
提示:以下是本篇文章正文内容,下面案例可供参考
一、按键功能定义
这里我将按键按住3秒视为长按操作,两次按下间隔0.5s视为双击,否则为单击
二、使用步骤
1.按键初始化
初始化部分和正常的独立按键使用一样,可以参考正点原子的代码
代码如下(示例):
这里使用的是上拉模式
//按键初始化
void CtrlKey_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//KEY0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置为上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化IO口
}
2.按键扫描函数(重点)
在key.h中对键值进行宏定义
代码如下(示例):
#define KEY0 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)//读取按键
#define KEY0_PRES 1 //单击
#define LONG_PRES 2 //长按
#define DOUBLE_PRES 3 //双击
在key.c中编写扫描函数,进行按键扫描并返回相应键值
代码如下(示例):
//为了代码不那么乱,这里我定义了一个结构体,不想使用结构体的可以直接定义全局变量
typedef struct {
u32 u32time1; //第一次按下后开始计时,主要用于判断长按,放在定时器中自加
u32 u32time2; //第一次松手后开始计时,用于判断双击或单击,放在定时器中自加
u8 u8key_flag; //第一次按下标志
u8 u8key_double_flag; //第二次标志
}Key_Tag;
Key_Tag skey;
u8 KEY_Scan()
{
static u8 press = 0;
if(KEY0==0)//按键按下
{
delay_ms(10);//消抖
if(KEY0==0)
{
if(skey.u8key_flag==0)
{
skey.u8key_flag=1; //第一次按下,标志位置1。同时计数值归零
skey.u32time1=0;
}
else if(skey.u8key_flag==1)
{
if(!press && skey.u32time1 > 3000)//如果第一次按下且时间超过3S,视为长按
{
press = 1;
return LONG_PRES;//返回长按键值
}
}
}
}
else if(KEY0==1)//按键松开
{
if(skey.u8key_flag==1) //第一次按键松开
{
skey.u8key_flag=0;
if(skey.u32time1>3000)//按下后超过3秒才松开,已经返回了键值,松手后把标志位都归零
{
press = 0;
skey.u32time1 = 0;
skey.u32time2 = 0;
skey.u8key_flag=0;
skey.u8key_double_flag=0;
}
else if(skey.u8key_double_flag==0)
{
skey.u8key_double_flag=1; //第一次松开之后标志位置1开始等待第二次按键松开
skey.u32time2=0;
}
else if(skey.u8key_double_flag==1)
{
if(skey.u32time2<500) //如果第二次松开时间间隔小于0.5S,视为双击
{
skey.u8key_double_flag=0;
return DOUBLE_PRES;
}
}
}
else if(skey.u8key_double_flag==1)
{
if(skey.u32time2>=500)
{
skey.u8key_double_flag=0;
return KEY0_PRES;//如果第一次松开之后0.5s没有第二次按键操作,视为短按
}
}
}
return 0;//没有按键按下返回0
}
3.注意事项
time1和time2两个计时变量要放在定时器中自加,这里就不放出详细代码了。
在main函数中轮询调用按键扫描函数,获得键值之后再根据键值执行相应操作。和平时的按键扫描函数一样用法
总结
这个实现按键单击双击长按的方法比较简单,主要是在按键按下之后记录第一次按下持续时间,若达到我们要的长按标准则视为长按,建议长按时间不小于1秒。第一次按键松手之后记录第二个时间,若在规定间隔时间内有第二次按下并松手则视为双击,若达到规定时间还没第二次按下并松手,则为单击。
小白入行没多久,第一次写博客,可能写得很一般,希望各位大神勿喷。如果有什么错误欢迎指正。