【BLE】TLSR8258开发记录之11--key扫描、单击双击、短按长按

1、说明

基于SDK3.4,在SDK中实现单个按键的长按短按、单击双击的识别

2、操作

A.在vendor/8258_ble_sample/MG_Application目录下新建MG_Key.c、MG_Key.h
其中MG_Key.c代码如下

#include "MG_Key.h"
#include "drivers.h"

#define key_state_0  0
#define key_state_1  1
#define key_state_2  2
#define key_state_3  3

/***************************************************************************
程序功能:一个按键的单击、双击、短按、长按。4种按键方式,然后做不同的处理。
***************************************************************************/
static unsigned char key_driver(void)
{
      static unsigned char key_state_buffer1 = key_state_0;
      static unsigned int key_timer_cnt1 = 0;
      unsigned char key_return = key_no;
      unsigned char key;
      unsigned char IO_Data;

      IO_Data = gpio_read(GPIO_PC4);//read the I/O states
      if(IO_Data)//IO设置为上拉输入,按键未按下时IO_Data为>0的数值,而不是为1
      {
            IO_Data = 1;
      }
      else
      {
            IO_Data = 0;
      }
      key = IO_Data;
      switch(key_state_buffer1)
      {
            case key_state_0:
                  if(key == 0)
                        key_state_buffer1 = key_state_1;
                        //按键被按下,状态转换到按键消抖和确认状态//
                  break;
            case key_state_1:
                  if(key == 0)
                  {
                        key_timer_cnt1 = 0;
                        key_state_buffer1 = key_state_2;
                        //按键仍然处于按下状态
                        //消抖完成,key_timer开始准备计时
                        //状态切换到按下时间计时状态
                  }
                  else
                        key_state_buffer1 = key_state_0;
                        //按键已经抬起,回到按键初始状态
                  break;  //完成软件消抖
            case key_state_2:
                  if(key == 1)
                  {
                        key_return = key_click;  //按键抬起,产生一次click操作
                        key_state_buffer1 = key_state_0;  //转换到按键初始状态
                  }
                  key_timer_cnt1++;
                  if(key_timer_cnt1 >= 200 && key_timer_cnt1< 500)  //按键继续按下,计时超过2000ms且不超过5000ms
                  {
                        key_state_buffer1 = key_state_3;  //转换到等待按键释放状态
                  }
                  if(key_timer_cnt1>=500)
                  {
                        key_state_buffer1 = key_state_3;  //转换到等待按键释放状态
                  }
                  break;
            case key_state_3:  //等待按键释放
                  if(key == 1)  //按键释放
                        {
                        printf("key is release\r\n");
                        printf("the timecnt is:%d\r\n",key_timer_cnt1);    //打印按键按下的时长
                        if(key_timer_cnt1 >= 200 && key_timer_cnt1< 500)   //按键继续按下,计时超过2000ms且不超过5000ms
                        {
                              key_return = key_long_2s;  //送回长按事件
                        }
                        if(key_timer_cnt1>=500)
                        {
                              key_return = key_long_5s;
                        }
                        key_state_buffer1 = key_state_0;  //切回按键初始状态
                        }
                  else
                  {
                        key_timer_cnt1++;
                  }
                  break;
      }
      return key_return;
}
/***************************************************************************
函数功能:中层按键处理函数,调用底层函数一次,处理双击事件的判断,
                                        返回上层正确的无键、单击、双击、短按、长按5种状态
本函数由上层循环调用,间隔10ms
***************************************************************************/
unsigned char key_read(void)
{
      static unsigned char key_state_buffer2 = key_state_0;
      static unsigned char key_timer_cnt2 = 0;
      unsigned char key_return = key_no;
      unsigned char key;
      key = key_driver();
      switch(key_state_buffer2)
      {
            case key_state_0:
                  if(key == key_click)
                  {
                        key_timer_cnt2 = 0;  //第一次单击,不返回,到下个状态判断是否会出现双击
                        key_state_buffer2 = key_state_1;
                  }
                  else
                        key_return = key;  //对于无键、长按,返回原事件
                  break;
            case key_state_1:
                  if(key == key_click)  //又一次单击,时间间隔小于500ms
                  {
                        key_return = key_double;  //返回双击事件,回到初始状态
                        key_state_buffer2 = key_state_0;
                  }
                  else if(++key_timer_cnt2 >= 50)
                  {
                        //这里500ms内肯定读到的都是无键事件,因为长按大于2000ms
                        //在2s前底层返回的都是无键
                        key_return = key_click;  //500ms内没有再次出现单击事件,返回单击事件
                        key_state_buffer2 = key_state_0;  //返回初始状态
                  }
                  break;
      }
      return key_return;
}

MG_Key.h的代码如下

#ifndef MG_KEY_H_
#define MG_KEY_H_

#include "tl_common.h"

#define key_no           0
#define key_click  1
#define key_double       2
#define key_long_2s      3
#define key_long_5s      4

//API
extern unsigned char key_read(void);

#endif /* MG_KEY_H_ */

B.在app.c的user_init_normal()函数中添加GPIO的初始化,将IO初始化为上拉输入

    gpio_set_func(GPIO_PC4,AS_GPIO);
    gpio_set_input_en(GPIO_PC4,1);
    gpio_setup_up_down_resistor(GPIO_PC4,PM_PIN_PULLUP_10K);

创建一个10ms的定时任务,将key_read()函数放于该任务中

blt_soft_timer_add(&my_key_event,10000);

C.在按键扫描任务中添加对按键结果的处理

int my_key_event()
{
      unsigned char temp = 0;
      temp = key_read();
      //printf("the temp is :%d\r\n",temp);
      switch(temp)
      {
            //单击
            case key_click:
            {
                  printf("key_click!\r\n");
                  break;
            }
            //双击
            case key_double:
            {
                  printf("key_double!\r\n");
                  break;
            }
            //短按2s
            case key_long_2s:
            {
                  printf("key_long_2s!\r\n");
                  break;
            }
            //长按5s
            case key_long_5s:
            {
                  printf("key_long_5s!\r\n");
                  break;
            }
            default:
                  break;
      }
      return 0;
      //break;
}

3、现象

将程序烧录并执行,分别进行【单击】、【双击】、【短按2s】、【长按5s】的操作
在这里插入图片描述
如上图,第1行为单击按键后的打印结果、第2行为双击按键后的打印结果、第3-5行为短按按键2s后的打印结果(231为按键按下的时长=10ms231=2.3秒)、第6-8行为长按按键5s后的打印结果(620为按键按下的时长=10ms620=6.2秒)

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值