打印

分享一个支持按键单双击的程序,在v7 按键的基础上修改而来,欢迎指正及纠正

[复制链接]
1678|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
卡拉瓦乔|  楼主 | 2018-8-4 07:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hpdell 于 2019-11-26 11:05 编辑

分享一个支持按键单双击的程序,在v7 按键的基础上修改而来,欢迎指正及纠正
目前已知问题,同时按下 组合键松手后貌似会触发 单击 发送 消息,这个有什么方法可以解决啊 ????????????

#define HARD_KEY_NUM            6                                   /* 实体按键个数 */
#define KEY_COUNT    (HARD_KEY_NUM + 1)        /* 6个独立建 + 1个组合按键 */


/*
        定义键值代码, 必须按如下次序定时每个键的按下、弹起和长按事件

        推荐使用enum, 不用#define,原因:
        (1) 便于新增键值,方便调整顺序,使代码看起来舒服点
        (2) 编译器可帮我们避免键值重复。
*/
#define  KEY_STATE_NUM                (4)        //按键状态数目
typedef enum
{
  KEY_NONE = 0,                        /* 0 表示按键事件 无任何按键按下 */

  KEY_1_DOWN,                                /* 1键按下 */
  KEY_1_UP,                                /* 1键弹起 */
  KEY_1_LONG,                                /* 1键长按 */
  KEY_1_CLOCK_2                ,                                /*  按键双击*/
//   3击
//   4击    等..... ,程序只需做简单的相关更改就可以了,同时修改 KEY_STATE_NUM 这个对应的数值即可

  KEY_2_DOWN,                                /* 2键按下 */
  KEY_2_UP,                                /* 2键弹起 */
  KEY_2_LONG,                                /* 2键长按 */
  KEY_2_CLOCK_2                ,                                /*  按键双击*/


  KEY_3_DOWN,                                /* 3键按下 */
  KEY_3_UP,                                /* 3键弹起 */
  KEY_3_LONG,                                /* 3键长按 */
  KEY_3_CLOCK_2                ,                                /*  按键双击*/

  KEY_4_DOWN,                                /* 4键按下 */
  KEY_4_UP,                                /* 4键弹起 */
  KEY_4_LONG,                                /* 4键长按 */
  KEY_4_CLOCK_2                ,                                /*  按键双击*/

  KEY_5_DOWN,                                /* 5键按下 */
  KEY_5_UP,                                /* 5键弹起 */
  KEY_5_LONG,                                /* 5键长按 */
  KEY_5_CLOCK_2                ,                                /*  按键双击*/

  KEY_6_DOWN,                                /* 6键按下 */
  KEY_6_UP,                                /* 6键弹起 */
  KEY_6_LONG,                                /* 6键长按 */
  KEY_6_CLOCK_2                ,                                /*  按键双击*/

        /* 组合键 */
  KEY_7_DOWN,                                /* 7键按下 */
  KEY_7_UP,                                /* 7键弹起 */
  KEY_7_LONG,                                /* 7键长按 */
  KEY_7_CLOCK_2                ,                                /*  按键双击*/   

}KEY_ENUM;


/* 按键FIFO用到变量 */
#define KEY_FIFO_SIZE        KEY_COUNT        



typedef struct
{
        unsigned char Buf[KEY_FIFO_SIZE];                /* 键值缓冲区 */
        unsigned char Read;                                        /* 缓冲区读指针1 */
        unsigned char Write;                                        /* 缓冲区写指针 */
        unsigned char Read2;                                        /* 缓冲区读指针2 */

  // 以下为双击使用变量定义
  unsigned char DoubleClickOutTime;  // 双击超时
  unsigned char DoubleClickN;
  unsigned char DoubleClickK;    //用于判断按键是双击、三击、四击等判断变量
  unsigned char DoubleClickValBak;
  unsigned char DoubleClickIdBak;
}KEY_FIFO_T;



void bsp_DetectKey(uchar i)
{

        KEY_T *pBtn;

        /*
                如果没有初始化按键函数,则报错
                if (s_tBtn.IsKeyDownFunc == 0)
                {
                        printf("Fault : DetectButton(), s_tBtn.IsKeyDownFunc undefine");
                }
        */

        pBtn = &s_tBtn;
        if (pBtn->IsKeyDownFunc())
        {
                if (pBtn->Count < KEY_FILTER_TIME)
                {
                        pBtn->Count = KEY_FILTER_TIME;
                }
                else if(pBtn->Count < (2 * KEY_FILTER_TIME))
//    else if(pBtn->Count < ( KEY_FILTER_TIME << 1))    //提高程序运行速度
                {
                        pBtn->Count++;
                }
                else
                {
                        if (pBtn->State == 0)
                        {
                                pBtn->State = 1;

                                /* 发送按钮按下的消息 */
                                bsp_PutKey((unsigned char)((KEY_STATE_NUM * i) + 1));  // +1 必须与 KEY_ENUM 这个枚举里面的定义的一致
                        }

                        if (pBtn->LongTime > 0)
                        {
                                if (pBtn->LongCount < pBtn->LongTime)
                                {
                                        /* 发送按钮持续按下的消息 */
                                        if (++pBtn->LongCount == pBtn->LongTime)
                                        {
                                                /* 键值放入按键FIFO */
                                                bsp_PutKey((unsigned char)((KEY_STATE_NUM * i) + 3));  // +3 必须与 KEY_ENUM 这个枚举里面的定义的一致
                                        }
                                }
                                else
                                {
                                        if (pBtn->RepeatSpeed > 0)
                                        {
                                                if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)
                                                {
                                                        pBtn->RepeatCount = 0;
                                                        /* 常按键后,每隔10ms发送1个按键 */
                                                        bsp_PutKey((unsigned char)((KEY_STATE_NUM * i) + 1));
                                                }
                                        }
                                }
                        }
                }
        }
        else
        {  
                if(pBtn->Count > KEY_FILTER_TIME)
                {
                        pBtn->Count = KEY_FILTER_TIME;
                }
                else if(pBtn->Count != 0)
                {
                        pBtn->Count--;
                }
                else
                {
                        if (pBtn->State == 1)     // 按钮弹起
                        {
                                pBtn->State = 0;
                                
        // 500ms 以内必须按下相同的按键才算是 某个按钮双击
        s_tKey.DoubleClickOutTime = 50;   // 每10ms调用一次, 50*10ms = 500ms
        s_tKey.DoubleClickK ++;
        s_tKey.DoubleClickIdBak = i;
        s_tKey.DoubleClickN = (unsigned char)((KEY_STATE_NUM * i) + 2);   // 计算按键抬起后的按键值,+2 必须与 KEY_ENUM 这个枚举里面的定义的一致

        // 以下为增加的 双击,目前双击调试基本成功 ,只是不太完美 2019.11.25
        if(s_tKey.DoubleClickK == 1)     // 按键按下抬起第一次
        {
          s_tKey.DoubleClickValBak = s_tKey.DoubleClickN;    // 备份备份按键抬起键值
        }
                        }
                }
                pBtn->LongCount = 0;
                pBtn->RepeatCount = 0;
        }


  // 按键抬起后,判断是双击还是单击事件, 基本实现,只是不太完美,后续再研究研究 ?  2019.11.25
  if((s_tKey.DoubleClickK >0) && (s_tKey.DoubleClickOutTime == 0)) {
    switch(s_tKey.DoubleClickK)
    {
      case 1:
          // 发送按钮弹起的消息
          bsp_PutKey((unsigned char)(s_tKey.DoubleClickValBak));
          s_tKey.DoubleClickK =0;
          s_tKey.DoubleClickN =0;
          break;

      case 2:
        s_tKey.DoubleClickN = (unsigned char)((KEY_STATE_NUM * s_tKey.DoubleClickIdBak) + 2);   // 计算按键抬起后的按键值,+2 必须与 KEY_ENUM 这个枚举里面的定义的一致
        if(s_tKey.DoubleClickValBak == s_tKey.DoubleClickN) {   //说明是 某个按键的 双击 事件
          // 发送双击按钮弹起的消息
          bsp_PutKey((unsigned char)((KEY_STATE_NUM * s_tKey.DoubleClickIdBak) + 4));        // +4 必须与 KEY_ENUM 这个枚举里面的定义的一致
        }
          s_tKey.DoubleClickValBak =0;
          s_tKey.DoubleClickN =0;
          s_tKey.DoubleClickK =0;
        break;

  //    case 3:  // 三击,目前没有使用
  //      break;

      default:
          s_tKey.DoubleClickValBak =0;
          s_tKey.DoubleClickN =0;
          s_tKey.DoubleClickK =0;
        break;
    }
  }
}


/*
*********************************************************************************************************
*        函 数 名: bsp_KeyScan
*        功能说明: 扫描所有按键。非阻塞,被systick中断 或者 定时器中断 周期性的调用,二者选择其一即可, 每隔10ms调用一次
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
void bsp_KeyScan(void)
{
        u8 i;
        for (i = 0; i < KEY_COUNT; i++)
        {
                bsp_DetectKey(i);
        }
  if(s_tKey.DoubleClickOutTime > 0)   s_tKey.DoubleClickOutTime--;
}


//---------------------------按键扫描---------------------------//
// 主程序调用

void KEY_San(void)
{
        uchar ucKeyCode = KEY_NONE;                /* 按键代码 */

        /* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */
        ucKeyCode = bsp_GetKey();        /* 读取键值, 无键按下时返回 KEY_NONE = 0 */               
         
        if (ucKeyCode != KEY_NONE)
        {
                switch (ucKeyCode)
                {


      case KEY_SELECT_UP:   //--------------------- 按键松手后,程序执行---------------------

      break;   


    case  KEY_SELECT_LONG:
      {

      }
      break;     

      case KEY_LEFT_UP:   //--------------------- 按键松手后,程序执行---------------------         
        {
          UART0_printf("发送按钮 单 击的消息
");
        }
        break;



    case  KEY_LEFT_CLICK_2:   // 双击测试
      {
        if(g_tMenu.menu == MAIN_DISPLAY_MENU)
        {
          UART0_printf("发送按钮 双 击的消息
");
        }
      }
      break;  

    case  KEY_SYS_DOWN:   // return 与 select 组合按键按下
      {
        if(g_tMenu.menu == MAIN_DISPLAY_MENU)
        {
          BEEP_KeyTone();
          UART0_printf("return 与 select 组合按键按下
");
        }
      }
      break;  

      default : break;
    }
  }
}

使用特权

评论回复

相关帖子

沙发
lhl0512| | 2023-9-20 10:50 | 只看该作者
谢谢分享

使用特权

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

本版积分规则

438

主题

438

帖子

0

粉丝