键值转换--复杂按键事件识别程序(链接层-优化版)

复杂按键事件识别程序(链接层-优化版)

本文相对于键值转换--复杂按键事件识别程序(链接层)文章中所述的按键事件转换程序进行优化(原来的代码太多,太杂,不易于维护)。

优点:代码简洁,易于修改和阅读。

缺点:无法区分某一特殊按键在不同的系统状态下的按键时间(比如同一个键在不同的情况下可以长按3s或则5s),连按和长按不能同时存在(也可以加条件进行区分)。

复杂按键包括多个按键的单按事件长按事件连按事件组合按键事件等。。。

单按事件在按下键松开时判定,其它按键情况在达到规定的时间后触发相应按键事件。

本程序为链接层程序,处理和识别按键驱动层扫描到的按键信息g_u8KeyValue。为了区分不同的按键与组合按键,g_u8KeyValue的每一位表示一个按键的按下情况。定义如下:

//宏定义各按键按下时的bit值
#define KEY_EVENT_NULL_CLICK     0x00
#define KEY_EVENT_CLOCK_CLICK    0x01
#define KEY_EVENT_DOWN_CLICK     0x02
#define KEY_EVENT_MODE_CLICK     0x04
#define KEY_EVENT_LOCK_CLICK     0x08
#define KEY_EVENT_ONOFF_CLICK    0x10
#define KEY_EVENT_SETTING_CLICK  0x20
#define KEY_EVENT_UP_CLICK       0x40
#define KEY_EVENT_TIMING_CLICK   0x80
#define KEY_EVENT_LONG_KEY_CLICK 0xff  //长按标志

//组合键
#define KEY_EVENT_SETTING_UP_CLICK     0x60
#define KEY_EVENT_SETTING_ONOFF_CLICK  0x30
#define Key_EVENT_MODE_UP_DOWN_CLICK   0x46

转换后的具体按键信息保存于g_KeyEvent结构体中。其定义如下:

typedef enum
{
  KeyValueNull = 0,
  KeyValueOnOff = 1,
  KeyValueMode  = 2,
  KeyValueClock = 3,
  KeyValueSetting = 4,
  KeyValueTiming = 5,
  KeyValueLock = 6,
  KeyValueUp = 7,
  KeyValueDown = 8,
  KeyValueOnOff1s = 9,
  KeyValueLock1s = 10,
  KeyValueMode3s = 11,
  KeyValueClock3s = 12,
  KeyValueSetting3s = 13,
  KeyValueUp3s = 14,
  KeyValueUp10s =15,
  KeyValueSettingUp3s = 16,
  KeyValueSettingOnOff5s = 17,
  KeyValueModeUpDown3s = 18,
  KeyValueUpLong = 19,
  KeyValueDownLong = 20,

}KEY_EVENT_E;

extern KEY_EVENT_E  g_KeyEvent;    //枚举按键事件  

优化后代码如下:

/* Private define ------------------------------------------------------------*/
#define KEY_PRESS_TIME  80      //单按最小时间
#define KEY_SINGLE_TIME 1000    //单按最大时间

typedef struct
{
   u16 short_time;         //是否有短按标志(组合键没短按 短按时间另定义)
   KEY_EVENT_E short_event;//短按事件
   u16 long_t;             //长按时间
   KEY_EVENT_E long_event; //长按事件
   u16 continue_t;         //连按时间间隔,连按默认触发的是短按事件

}KEY_BUTTON_T;

//定义了系统中需要的按键组合
KEY_BUTTON_T key_long         = {0, KeyValueNull, 0, KeyValueNull, 0},          //long中没有任何事件
             key_up           = {1, KeyValueUp, 0, KeyValueUp3s, 500},
             key_set          = {1, KeyValueSetting, 3000, KeyValueSetting3s, 0},
             key_clock        = {1, KeyValueClock, 3000, KeyValueClock3s, 0},
             key_down         = {1, KeyValueDown, 0, KeyValueNull, 500},
             key_mode         = {1, KeyValueMode, 3000, KeyValueMode3s, 0},
             key_lock         = {1, KeyValueLock, 1000, KeyValueLock1s, 0},
             key_onoff        = {1, KeyValueOnOff, 1000, KeyValueOnOff1s, 0},
             key_timing       = {1, KeyValueTiming, 0, KeyValueNull, 0},
             key_set_up       = {0, KeyValueNull, 3000, KeyValueSettingUp3s, 0},
             key_set_onoff    = {0, KeyValueNull, 5000, KeyValueSettingOnOff5s, 0},
             key_mode_up_down = {0, KeyValueNull, 3000, KeyValueModeUpDown3s, 0};

/* Private functions ---------------------------------------------------------*/
static KEY_BUTTON_T rFindKeyObject(u8 key_event);

/* Public functions ----------------------------------------------------------*/
void  Link_KeyValueGet(void);
void  Link_KeyEventTrans(void);

/*******************************************************************************
#Function      :   Link_KeyValueGet
#Description   :   获取键值(按键事件)
#Parameter     :   NULL
#Return        :   NULL
#AuthorAndData :   huangzhigang 20141027
*******************************************************************************/
void  Link_KeyValueGet(void)
{
   vDrv_KeyScanning();     //驱动层按键扫描

   Link_KeyEventTrans();   //链接层转换成按键事件(应用层处理)
}

/*******************************************************************************
#Function      :   Link_KeyEventTrans
#Description   :   按键事件转换(短按、长按、连按、组合键) 长按事件只能有一个有效
#Parameter     :   NULL
#Return        :   NULL
#AuthorAndData :   huangzhigang 20141027
*******************************************************************************/
void  Link_KeyEventTrans(void)
{
   static u8 s_u8ContinuePressFlag = 0;   //连按标志  用于区分连按与短按事件
   static KEY_BUTTON_T key_tmp;           //临时的按键对象
   static TIMER_T KeyDelayTime;           //按键时间
   static uint8_t KeyBackUp = KEY_EVENT_NULL_CLICK; //按键状态备份

   TimeMs(&KeyDelayTime);

   if(g_u8KeyValue)                               //有按键按下 则做相应的处理
   {
      if(KeyBackUp != g_u8KeyValue)
      {
         KeyDelayTime.DelayTime = 0;
         KeyBackUp = g_u8KeyValue;
         key_tmp  = rFindKeyObject(g_u8KeyValue);
      }

      if(key_tmp.continue_t && (KeyDelayTime.DelayTime >= key_tmp.continue_t))
      {
         g_KeyEvent = key_tmp.short_event;        //连按时间成立
         KeyBackUp = KEY_EVENT_NULL_CLICK;        //清楚备份  下次可以继续进入这里
         s_u8ContinuePressFlag = 1;
      }
      else if(key_tmp.long_t &&(KeyDelayTime.DelayTime >= key_tmp.long_t))
      {
         g_KeyEvent = key_tmp.long_event;         //长按事件成立
         key_tmp = key_long;
      }
   }
   else                                           //无按键按下 如果是松开按键的时刻 则进行单按检测
   {
      if(s_u8ContinuePressFlag)                   //连按时不检测短按事件
      {
         s_u8ContinuePressFlag = 0;
         KeyBackUp = KEY_EVENT_NULL_CLICK;
      }

      if(KeyBackUp && key_tmp.short_time)         //有值则表示是松开的时刻
      {
         if(key_tmp.short_time &&(KeyDelayTime.DelayTime >= KEY_PRESS_TIME)
            && (KeyDelayTime.DelayTime <= KEY_SINGLE_TIME))
         {
            g_KeyEvent = key_tmp.short_event;     //短按事件成立
         }

         KeyBackUp = KEY_EVENT_NULL_CLICK;
      }
      else                                        //没有值 表示空闲状态  无键按下
      {
         KeyBackUp = KEY_EVENT_NULL_CLICK;
         g_KeyEvent = KeyValueNull;               //清除键值
      }

      KeyDelayTime.DelayTime = 0;
   }
}

/*******************************************************************************
#Function      :   rFindKeyObject
#Description   :   找到按键对象并返回 key_long 定义了一种空对象 系统不做处理
#Parameter     :   NULL
#Return        :   当前按键所对应的按键对象
#AuthorAndData :   huangzhigang 20141027
*******************************************************************************/
static KEY_BUTTON_T rFindKeyObject(u8 key_event)  //找到按键对象
{
   switch(key_event)
   {
   case KEY_EVENT_NULL_CLICK:
      return key_long;
   case KEY_EVENT_CLOCK_CLICK:
      return key_clock;
   case KEY_EVENT_DOWN_CLICK:
      return key_down;
   case KEY_EVENT_MODE_CLICK:
      return key_mode;
   case KEY_EVENT_LOCK_CLICK:
      return key_lock;
   case KEY_EVENT_ONOFF_CLICK:
      return key_onoff;
   case KEY_EVENT_SETTING_CLICK:
      return key_set;
   case KEY_EVENT_UP_CLICK:
      return key_up;
   case KEY_EVENT_TIMING_CLICK:
      return key_timing;
   case KEY_EVENT_SETTING_UP_CLICK:
      return key_set_up;
   case KEY_EVENT_SETTING_ONOFF_CLICK:
      return key_set_onoff;
   case Key_EVENT_MODE_UP_DOWN_CLICK:
      return key_mode_up_down;
   case KEY_EVENT_LONG_KEY_CLICK:      //长按标志
      return key_long;
   default:
      return key_long;
   }
}
时间: 2024-11-01 06:46:37

键值转换--复杂按键事件识别程序(链接层-优化版)的相关文章

键值转换--复杂按键事件识别程序(链接层)

复杂按键事件识别程序(链接层) 复杂按键包括多个按键的单按事件.长按事件.连按事件.组合按键事件等 本程序为链接层程序,处理和识别按键驱动层扫描到的按键信息g_u8KeyValue.(g_u8KeyValue的每一位表示一个按键) 单按事件在按下键松开时判定,其它按键情况在达到规定的时间后触发相应按键事件. 宏定义: //宏定义各按键按下时的bit值 #define KEY_EVENT_NULL_CLICK 0x00 #define KEY_EVENT_CLOCK_CLICK 0x01 #def

Redis集群环境下的键值空间监听事件实现方案

一直想记录工作中遇到的问题和解决的方法,奈何没有找到一方乐土,最近经常反思,是否需要记录平时的点滴,后台还是决定下定决心记录一些,以便以后用到的时候找不着,实现这样的一个功能主要也是业务所需要的. 需求:要求统计所有会员在线人数,并根据会员在线状态同步改变人数. 之前用户登录使用session去控制,那么可以通过session进行在线用户人数统计,后来实现无状态不在依赖session作为用户在线的标准,使用Redis替换了Session,那么用户直接退出也好做,但是会存在用户直接关闭页面的情况,

Android : 输入设备键值映射流程

一.Android输入子系统简介: Android输入事件的源头是位于/dev/input/下的设备节点,而输入系统的终点是由WMS管理的某个窗口.最初的输入事件为内核生成的原始事件,而最终交付给窗口的则是KeyEvent或MotionEvent对象.因此Android输入系统的主要工作是读取设备节点中的原始事件,将其加工封装,然后派发给一个特定的窗口以及窗口中的控件.这个过程由InputManagerService(以下简称IMS)系统服务为核心的多个参与者共同完成. 图1:输入系统的总体流程

20150218【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

[改进Poll定时查询]IMX257实现GPIO-IRQ中断按键获取键值驱动程序 2015-02-18 李海沿 按键驱动程序中,如果不使用read函数中使程序休眠的,而是还是使用查询方式的话,可以使用Poll函数,来控制一定时间内,如果有按键发生,则立即返回键值. 同时,poll也可以同时监控多个(比如说按键,鼠标,等)一旦发生事件则立即返回. 我们在linux查看帮助: 从帮助中的说明得知, poll, ppoll - wait for some event on a file descrip

20150218【改进】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

[改进]IMX257实现GPIO-IRQ中断按键获取键值驱动程序 2015-02-18 李海沿 一.使用struct pin_desc 管理按键的值 1.定义结构体 2.将前面我们申请中断时写的(void *)1修改为 &pins_desc[n] 在ioctl中,设置中断中修改 在key_release中释放中修改 3.在中断程序中利用我们定义的struc pins_desc判断并得到按键的值 4.得到按键键值后,唤醒程序,在read函数中返回键值 附上驱动源程序: 1 /***********

20150218【改进信号量】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

[改进信号量]IMX257实现GPIO-IRQ中断按键获取键值驱动程序 2015-02-18 李海沿 前面我们使用POLL查询方式来实现GPIO-IRQ按键中断程序 这里我们来使用信号量,让我们的驱动同时只能有一个应用程序打开. 一.首先在前面代码的基础上来一个简单的信号 1.定义一个全局的整形变量 2.在打开函数中,每次进入打开函数canopen都自减1, 3.当我们不使用时,在realease 中canopen自加1 4.这样就实现了一个简单的信号量,我们编译,测试 当我们使用两个应用程序来

linux下input event事件,可以用后台截取键盘按下的键值,后台截取数据.....input.h

如何读取Linux键值,输入子系统,key,dev/input/event,dev/event,C语言键盘? 这里先上一段代码,自己拿到linux系统运行就可以,注意代码中keys_fd = open("/dev/input/event2", O_RDONLY);      这里去你的/dev/input/event2的event事件,去查看你的键盘事件是那一个,如果是event3那么你改成event3好了.这里给一个命令你去查看 cat  /proc/bus/usb/devices

Spark常用函数讲解--键值RDD转换

摘要: RDD:弹性分布式数据集,是一种特殊集合 ‚ 支持多种来源 ‚ 有容错机制 ‚ 可以被缓存 ‚ 支持并行操作,一个RDD代表一个分区里的数据集RDD有两种操作算子:         Transformation(转换):Transformation属于延迟计算,当一个RDD转换成另一个RDD时并没有立即进行转换,仅仅是记住       了数据集的逻辑操作         Ation(执行):触发Spark作业的运行,真正触发转换算子的计算 本系列主要讲解Spark中常用的函数操作:   

ios 解决数据请求json解析字典后,由于java某些类库转换json字符串后出现键值为&lt;null&gt;无法保存在userDefault的问题

解决数据请求json解析字典后,由于java某些类库转换json字符串后出现键值为<null>无法保存在userDefault. 打印下得到的字典数据: “username”=<null> 此时如果将字典保存到userDefault中会报错 所以需要遍历字典将其替换 for (NSString*s in [Dict1 allKeys]) { if ([Dict1[s] isEqual:[NSNull null]]) { [Dict1 setObject:@""