定时器按键,单击、长按、连发的实现问题

2019-07-23 16:37发布

现在设置一个按键实现单击、长按、连发(按下不抬起,每0.5s变量增加一次)三个功能,使用状态机的方法。单击、长按可以实现,但是连击无法实现,请大家帮忙看下,这个问题出在哪里呢。
我先用一个函数判断出单击和长按,再用一个函数先将长按筛选出去,在单击情况下判断是单击还是连发。
程序如下:
  1. #define N_key    0             //无键
  2. #define S_key    1             //单键
  3. #define C_key    2             //连键
  4. #define L_key    3             //长键

  5. #define key_state_0  0
  6. #define key_state_1  1
  7. #define key_state_2  2
  8. #define key_state_3  3

  9. //******************短按,长按功能函数***************//
  10. Uint16 read_key()
  11. {
  12.    static Uint16 key_state = 0,key_time=0; //key1_state 要定义为全局变量
  13.    Uint16 key_press,key_return=N_key;

  14.    key_press = GpioDataRegs.GPBDAT.bit.GPIO54;         // 读按键 I/O 电平
  15.    switch (key_state)
  16.   {
  17.      case key_state_0:        // 按键初始态
  18.        if (!key_press) key_state = key_state_1;  // 键被按下,状态转换到键确认态
  19.        break;

  20.      case key_state_1:        // 按键确认态
  21.        if (!key_press)
  22.     {
  23.          key_time = 0;
  24.         // key_return = 1;      // 按键仍按下,按键确认输出为“1”
  25.          key_state = key_state_2;  // 状态转换到键释放态
  26.     }
  27.     else
  28.          key_state = key_state_0;  // 按键已抬起,转换到按键初始态
  29.        break;

  30.      case key_state_2:
  31.        if (key_press)
  32.         {
  33.                         key_return = S_key;        // 此时按键释放,说明是产生一次短操作,回送S_key
  34.                    key_state = key_state_0;   // 转换到按键初始态
  35.         }
  36.        else if (++key_time >= 100)     // 继续按下,计时加10ms(10ms为本函数循环执行间隔)
  37.         {
  38.              key_return = L_key;        // 按下时间>1000ms,此按键为长按操作,返回长键事件
  39.              key_state = key_state_3;   // 转换到等待按键释放状态
  40.         }
  41.        break;
  42.        //key_state = key_state_0;  //按键已释放,转换到按键初始态
  43.        //break;

  44.         case key_state_3:                 // 等待按键释放状态,此状态只返回无按键事件
  45.         if (key_press) key_state = key_state_0; //按键已释放,转换到按键初始态
  46.         break;  
  47.        }
  48.      return (key_return);
  49.              }

  50. //******************连续按键功能函数***************//
  51. Uint16 key_read()
  52. {
  53.     static Uint16 key_m = key_state_0, key_time_1 = 0;
  54.     Uint16 key_return = N_key,key_temp;
  55.      
  56.     key_temp = read_key();
  57.      
  58.     switch(key_m)
  59.     {
  60.         case key_state_0:
  61.             if (key_temp == S_key )
  62.             {
  63.                  key_time_1 = 0;               // 第1次单击,不返回,到下个状态判断后面是否出现双击
  64.                  key_m = key_state_1;
  65.             }
  66.             else
  67.                  key_return = key_temp;        // 对于无键、长键,返回原事件
  68.             break;

  69.             case key_state_1:
  70.                    if (GpioDataRegs.GPBDAT.bit.GPIO54==1)
  71.                         {
  72.                                   key_m = key_state_0;  // 按键已释放,转换到按键初始态
  73.                                   key_return = 1;      // 输出“1”
  74.                            }
  75.                        else if (++key_time_1 >= 100)   // 按键时间计数
  76.                     {
  77.                           key_m = key_state_2;  // 按下时间>1s,状态转换到计时 2
  78.                            key_time_1 = 0;       // 清按键计数器
  79.                            key_return = 2;      // 输出“2”
  80.                     }
  81.                        break;

  82.                         case key_state_2:
  83.                         if (GpioDataRegs.GPBDAT.bit.GPIO54==1)
  84.                             key_m = key_state_0; //按键已释放,转换到按键初始态
  85.             else
  86.             {
  87.                              if (++key_time_1 >= 50)    // 按键时间计数
  88.                             {
  89.                                    key_time_1 = 0;     // 按下时间>0.5s,清按键计数器
  90.                             key_return = 2;    // 输出“2”
  91.                              }
  92.                     }
  93.                 break;

  94.     }
  95.           return key_return;
  96. }
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。