打印
[DemoCode下载]

按键检测

[复制链接]
1027|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
短按操作:按键按下。按下时间<1s,属于短按操作
长按操作:按键按下。时间>1s,属于长按操作

长按事件:任何1次出现的长按操作都属于长按事件
单机事件:1次短按操作后,间隔0.5内没有短按操作
双击事件:2次短按操作间隔事件<0.5s,则2次短按操作为1次双击事件,,且2次短按都消失
沙发
天灵灵地灵灵|  楼主 | 2017-7-20 16:46 | 只看该作者
#define  N_Key 0   无键
#define  S_Key 1   单键
#define  D_Key 2   双键
#define  L_Key 10   长键
#define  T-Key 3    3次点击
#define  F-Key 4   4次点击
#define  V_Key 5    5次点击

#define Key_state_0   0
#define Key_state_1   1
#define Key_state_2   2
#define Key_state_3   3
#define Key_state_4   4

unsigned char key_driver(void)
{
   static unsigned char key_state = key_state_0, key_time = 0;
   unsigned char key_press, key_return = N_key;
  key_press=key_input;    //读按键I/O电平
  switch(key_state)
  {
    case key_state_0:
     if(!key_press)    //如果键被按下,状态转换到按键消抖和确认状态
      key_state=key_state_1;
      break;
    case key_state_1:
     if(!key_press)
      {
        key_time=0;
        key_state=key_state_2; //按键仍然处于按下,消抖完成,状态切换到按下键时间的计时状态,但返回的无键状态
      }      
      else
        key_state=key_state_0;//按键已抬起,转换到按键初始态。此处完成和实现软件消抖,其实按键的按下和释放都在此消抖的
     break;
     
     case key_state_2:
      if(key_press)
      {
       key_return=S_Key;     //此时按键释放,说明是产生一次端操作,回送S_key
       key_state=key_state_0;
      }
      else if(++key_time>=100)//继续按下,计时加10ms(定时器为10s)
      {
        key_retuen=L_Key;   //按下时间>1000ms,此按键位长按操作,返回长按事件
        key_state=key_state_3;   转换到等待按键释放状态
      }
  
  }

}
unsigned char  key_read(void)
{
  static unsigned char key_m=key_state_0,key_time_1=0;
  unsigned char key_return=N_Key,key_temp;
  key_temp=key_driver();
   switch(key_m)
   {
     case key_state_0:
      if(key_temp==S_Key)
      {
        key_time_1=0;  //第一次单机,不返回,到下个状态判断返回后面是否出现双击
        key_m=key_state_1;
      }
      else
       key_return=key_temp;
      
       break;
     case  key_state_1:
      if(key_temp==S_Key)   // 又一次单击(间隔肯定<500ms)
      {
       key_return=D_Key;     // 返回双击键事件,
       key_m=key_state_2;    //第二次单机,不返回,到下个判断是否出现三击
      }
      else
      {
       if(++key_time_1>=50)
       {
         key_return=S_Key;  //500ms内没有再次出现单键事件,返回上一次的事件
         key_m=Key_state_0;//返回初始状态
       }
      }
      break;
      case key_state_2:
       if(key_temp==S_Key)
       {
         key_return=T_Key;  //返回三击键事件
         key_m=key_state_3; //第三次单机,不返回,到下个判断是否出现三击
       }
       else
       {
         if(++key_time>=50)
         {
            key_return=D_Key;
            key_m=key_state_0;
         }
      
       }
       break;
       case key_state_3:
        if(key_temp==S_Key)
        {
          key_return=F_Key;  //返回四击键事件
          key_m=key_state_4;//第四次单机,不返回,到下个判断是否出现三击
        }
        else
        {
          if(++key_time_1>=50)
          {
            key_return=T_Key;
            key_m=key_state_0;
          }
        }
        break;
        case key_state_4:
         if(key_temp==S_Key)
         {
          key_return=V_Key;  //返回五击键事件,回初始状态
          key_m=key_state_0;//第五次单机,不返回,到下个判断是否出现三击
         }
         else
         {
         if(++key_time_1>=50)
         {
                key_return=F_Key;
               key_m=key_state_0;
         }
   
         }
         break
         
   }

    return key_return;
}

void T1_INT_INTERRUPT interrupt 3
{
  time_10ms_ok=1;

}

void initTimer1(void)
{
  TIMER1_MODE1_ENABLE;
  TH1 = (65536-TIMER1_10MS_VALUE)/256;
  TL1 = (65536-TIMER1_10MS_VALUE)%256;
  set_ET1;
  set_EA;
  set_TR1;
}

void mian(void)
{
  while(1)
  {
   if(time_10ms_ok)
   {
     time_10ms_ok=0;
     key=key_read();
     switch(key)
     {
      case S_Key:   //单击事件
        break;
      case D_Key:   //双击事件
        break;
      case T-Key:   //三击事件
        break;
      case F-Key:    //四击事件
        break;
      case V_Key:   //五击事件
        break;
     
     }
   }
  
  }

}

使用特权

评论回复
板凳
yiyigirl2014| | 2017-7-20 20:14 | 只看该作者
充分利用了定时器的用处。

使用特权

评论回复
地板
wahahaheihei| | 2017-7-20 21:08 | 只看该作者
果然是定时器好用的。

使用特权

评论回复
5
gejigeji521| | 2017-7-20 21:15 | 只看该作者
嗯,这个就是实现长按和短按的方式。

使用特权

评论回复
6
wahahaheihei| | 2017-7-21 16:51 | 只看该作者
按下时候等定时器触发计时?

使用特权

评论回复
7
643757107| | 2017-7-23 11:41 | 只看该作者
极具参考价值的代码

使用特权

评论回复
8
稳稳の幸福| | 2017-7-23 13:16 | 只看该作者
switch case很适合用。

使用特权

评论回复
9
598330983| | 2017-7-23 18:03 | 只看该作者
果断收藏了,留着用

使用特权

评论回复
10
座机呀| | 2017-8-29 23:09 | 只看该作者
使用定时器避免了delay,但是相对于使用delay,筛子的密度没有减小,因为消抖只消了一次,而且这样的代码不好拓展,不适合多个按键,每个按键需求又有一些不一样的情况。假如有组合按键,又得大改了。

使用特权

评论回复
11
jiekou001| | 2017-8-31 15:04 | 只看该作者
学习学习,是不是有个单片机带个寄存器专门控制这个案件防抖。

使用特权

评论回复
12
18123784178| | 2017-10-6 10:01 | 只看该作者
还不错哦

使用特权

评论回复
13
jiekou001| | 2017-10-6 10:45 | 只看该作者
按下去后计时器的妙用。

使用特权

评论回复
14
ailingg| | 2017-12-10 11:25 | 只看该作者
代码夹杂中文,比如“()”“:”,有返回的函数没有返回,引用的变量名和声明的不一致。总之,缺乏诚意。

使用特权

评论回复
15
wanduzi| | 2017-12-10 22:48 | 只看该作者
仔细想了想,好多觉得复杂,是因为变量名做的太复杂了。

使用特权

评论回复
16
捉虫天师| | 2017-12-11 21:38 | 只看该作者
有时候用防抖处理却造成了按键不灵敏。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

161

主题

3317

帖子

13

粉丝