独立按键检测短按、长按,松手后响应操作

背景

有项目使用独立按键检测,短按、长按。根据使用效果,发现松手后,也就是按键弹起后响应操作比较好操作。

记得之前,博主写过一篇关于按键的检测的文章,但是过于复杂了。可能很难懂,这里就简单一点,只处理一个按键。并且这个按键,只检测短按、长按两种状态。

硬件

硬件原理图如下

这里不管使用哪个型号的MCU基本上都一样了,就是按键上拉,按下按键MCU管脚有个低电平输入信号。如下图所示,这里允许我偷个懒,把之前的图拿上来。因为实际项目的图,拿上来影响不好。反正原理就是这样的,你也可以将KEY上拉,这里的上拉可以在MCU的管脚配置为输入上拉。

如下图所示按下按键,单片机管脚KEY得到一个低电平输入。

 软件

这里就不限于使用的MCU,按键采用扫描的方式,获取按键值。

首先使用定时器定时1ms

这段代码是根据使用的MCU平台实现定时器的初始化配置,保证定时器中断1ms来一次,不同的MCU平台这里的代码都不一样的。例如STM32/GD32/等等其他的8位的MCU都可以。

void timer_init(void)
{

    //根据MCU平台实现,初始化代码

}

定时器中断函数,实现按键扫描

这里的key_val/key_val_buf你可以理解上全局变量,读取按键消息,如果有按键就将按键值保存下来。


void    TIM_IRQHandler()
{

		key_val = ReadKey();
		if(key_val != NO_KEY)
		{
			key_val_buf = key_val;
		}
		

}  

具体检测长按的函数,这里是最关键

用一个状态机实现

代码如下

这里简单解释一下,每次定时器中断来,首先读取按键的管脚的当前值

如果状态0,检测到有按键按下,进入状态1,消除抖动

状态1确认有按键按下,则进入状态2

状态2等待按键松手,根据KeyTimeCnt 的数值来确定输出长按还是短按

这里2ms到1000ms为短按
1000ms以上认为短按

这个数值可以根据你自己的使用习惯进行调整。我这里也是根据实际按键的效果来调整得到的。


unsigned char ReadKey(void)
{
	static unsigned char KeyState = 0;
	static unsigned int KeyTimeCnt = 0;
	static unsigned int no_key_times = 0;
	unsigned char KeyReturn = NO_KEY;
	static unsigned char KeyCurValue = NO_KEY;
	KeyCurValue = key; //读取按键值

	switch(KeyState)
	{
		case 0:
		{
            if(KeyCurValue == 0)        //检测到有键按下
            {
               KeyState++;                   //转到消抖确认状态 
               KeyTimeCnt = 0;
			   no_key_times = 0;
            }
			else
			{
				no_key_times++;
				if(no_key_times >= 500)//500*20ms=10s
				{
					no_key_times = 0;
				}
			}
			break;
		}
        case 1:
		{
            if(KeyCurValue == 0)   //和上次按键相同确认有键按下
            {
				KeyState++;                  //转入等待按键释放状态
			
            }
            else
                KeyState--;                  //两次键值不同 返回等待按键状态
            KeyTimeCnt = 0; 
			break;
		}
		//增加时间按键的长按、短按检测
		case 2:  
		{
			if(NO_KEY == KeyCurValue)           // 按键已经释放
			{
				if((KeyTimeCnt > 2) && (KeyTimeCnt < 1000))     
				{
					KeyReturn = KEY1_DOWN;  
					KeyTimeCnt = 0; 
					KeyState = 0;
				}
				else if(KeyTimeCnt >= 1000)
				{
					KeyReturn = KEY1_DOWN_LONG;  //检测到长按
					KeyTimeCnt = 0; 
					KeyState = 0;
				}
				else
				{
					KeyReturn = NO_KEY;
					KeyTimeCnt = 0; 
					KeyState = 0;
				}
			}
			else
			{
				KeyTimeCnt++;
				
			}
			break;
		}
		default:
		{
			KeyState = 0;
			break;
		}
    }
    return KeyReturn;
}

之前的博客,也可以参考,有点复杂

这个按键检测就复杂很多了

STM32独立按键扫描,支持同时按下、长按、快速键值_stm32按键扫描_大牛攻城狮的博客-CSDN博客

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大牛攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值