ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

STM32独立按键实现单击双击长按功能

2021-07-28 14:02:04  阅读:384  来源: 互联网

标签:u8key skey 单击 按下 STM32 flag 按键 GPIO 双击


提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

在使用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秒。第一次按键松手之后记录第二个时间,若在规定间隔时间内有第二次按下并松手则视为双击,若达到规定时间还没第二次按下并松手,则为单击。

小白入行没多久,第一次写博客,可能写得很一般,希望各位大神勿喷。如果有什么错误欢迎指正。

标签:u8key,skey,单击,按下,STM32,flag,按键,GPIO,双击
来源: https://blog.csdn.net/weixin_48753720/article/details/119175681

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有