打印

紧急请教一个关于键盘处理的问题!谢谢!

[复制链接]
2131|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lzm2008|  楼主 | 2011-2-24 18:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
假设我要显示四个不同的界面状态,分别给变量DisplayMode赋相应的值表示:
DisplayMode=0;
DisplayMode=1;
DisplayMode=2;
DisplayMode=3;

同一个按键(Key1),当 短按 的时候进入(DisplayMode=1)界面,
当 长按 的时候进入(DisplayMode=3)界面;
但是如果已经进入了(DisplayMode=1或者DisplayMode=2)界面,则长按按键(Key1)也不能进入(DisplayMode=3)界面;
如果进入(DisplayMode=1)界面则按下确认键(Key4)时,切换到(DisplayMode=2)界面;再次按下确认键(Key4)时,切换到(DisplayMode=0)界面;

我参照的是网友的状态机程序,但是感觉总是不对劲,因为每次都是得进入短按才能进入长按。所以实现上面的要求似乎很不和逻辑,想请教一下,给个思路如何处理上面的按键功能,谢谢!



#include<reg51.h>
  unsigned int KeyValue;//键盘值全局变量
  unsigned int DisplayMode=0;
  bit flag=1;
//根据按键接口定义的按键键值(P1口接了5个按键,目前只用到Key1和key4)
#define Key1   0X17  //0001 0111
#define Key2   0X1E  //0001 1110
#define Key3   0X1D  //0001 1101
#define Key4   0X1B  //0001 1011
#define Key5   0X0F  //0000 1111
#define Key6  0x1C  //0001 1100
#define KeyNull     0x1F  //0001 1111
//按键状态
#define KEY_INIT   0  //初始状态
#define KEY_WOBBLE   1  //消抖状态
#define KEY_PRESS   2  //按下
#define KEY_LONG   3  //长按
#define KEY_CONTINUE  4  //连发
#define KEY_RELEASE  5  //释放
//定义长按键的计数,以及连发间隔的计数
#define KEY_LONG_COUNT   350
#define KEY_CONTINUE_COUNT  10
//定义按键返回值状态(按下,长按,连发,释放)
#define KEY_DOWN_PRESS  0X80 //按下
#define KEY_LONG_PRESS  0X40 //长按
#define KEY_CONTINUE_PRESS  0X20 //连发
#define KEY_UP     0X10 //释放

//读键盘值
void GetKey(unsigned int *pKeyValue)
{
static unsigned int KeyState = KEY_INIT;
static unsigned int KeyTimeCount=0;

static unsigned int LastKey=KeyNull;//保存按键释放时候的键值

unsigned int KeyTemp=KeyNull;
KeyTemp=P1;//读取P1口的状态

switch(KeyState)
{
  case KEY_INIT:
   {
    if(KeyNull != (KeyTemp))
    {
     KeyState=KEY_WOBBLE;
    }
   }
   break;
  case KEY_WOBBLE://消抖
   {
    KeyState=KEY_PRESS;
   }
   break;
  case KEY_PRESS://按下
   {
    if(KeyNull != (KeyTemp))//确实有按键按下
    {
     //保存键值
     LastKey=KeyTemp;    //
     KeyTemp |= KEY_DOWN_PRESS;//按键按下
     KeyState=KEY_LONG;
    }
    else
    {
     KeyState=KEY_INIT;
    }
   }
   break;
  case KEY_LONG://长按
   {
    if(KeyNull != (KeyTemp))
    {
     if(++KeyTimeCount>KEY_LONG_COUNT)
     {
      KeyTimeCount=0;
      //长按键事件发生
      LastKey=KeyTemp;//
      KeyTemp |= KEY_LONG_PRESS;
      KeyState=KEY_CONTINUE;
     }
    }
    else
    {
     KeyState=KEY_RELEASE;
    }
   }
   break;
  case KEY_CONTINUE://连发
   {
    if(KeyNull != (KeyTemp))
    {
     if(++KeyTimeCount>KEY_CONTINUE_COUNT)
     {
      KeyTimeCount=0;
      LastKey=KeyTemp;//
      KeyTemp |= KEY_CONTINUE_PRESS;
     }
    }
    else
    {
     KeyState=KEY_RELEASE;
    }
   }
   break;
  case KEY_RELEASE://释放
   {
  
    LastKey|=KEY_UP;
    KeyTemp=LastKey;
    KeyState=KEY_INIT;
   }
   break;
  default:
   break;
}
*pKeyValue=KeyTemp;//返回键值
}

//键盘值处理
void Key_Process(void)
{
switch(KeyValue)
{
  case Key1|KEY_DOWN_PRESS:  //短按设置键
   
    DisplayMode=1;
   break;
   
  case Key1|KEY_LONG_PRESS: //长按设置键
  
   if(flag)
   {
    DisplayMode=3;
   }
   
   break;
   
  case Key4|KEY_DOWN_PRESS://确认键
  
   DisplayMode++;
   if(DisplayMode==3){DisplayMode=0;}
   break;
  default:
   break;
}
if(DisplayMode==1||DisplayMode==2||DisplayMode==3)
{
  flag=0;
}
else
{
  flag=1;
}
}
void main(void)
{
while(1)
{
  GetKey(&KeyValue);
  Key_Process();
}
}

KeyScan.rar

30.51 KB

相关帖子

沙发
lzm2008|  楼主 | 2011-2-24 18:26 | 只看该作者
抱歉,不知道为什么贴上去的代码这么乱!

使用特权

评论回复
板凳
红金龙吸味| | 2011-2-24 18:34 | 只看该作者
设定一个标志,g_bLongProcess = 1 ;
case KEY_LONG://长按状态
如果没有检测到长按 则g_bLongProcess = 0 ;

case Key1|KEY_DOWN_PRESS:  //短按设置键
   
        if(!g_bLongProcess)
      {
            DisplayMode=1;
      }
       break;

使用特权

评论回复
地板
xwj| | 2011-2-24 18:37 | 只看该作者
按下时不要立即返回按下(短按)键值,而应该在按键释放时判断没有长按键 才返回短按键值。

使用特权

评论回复
5
xwj| | 2011-2-24 18:38 | 只看该作者
抄别人的程序是要动脑筋,要学会根据自己的需要来进行修改:P

使用特权

评论回复
6
ayb_ice| | 2011-2-24 19:03 | 只看该作者
1:要按键松开才有效,
2:松开时判断连续按下的时间,若小于1S视为短按键,大于2S视为长按键,1~2S无效

使用特权

评论回复
7
lzm2008|  楼主 | 2011-2-27 11:29 | 只看该作者
谢谢各位,xwj大叔批评的很对!

使用特权

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

本版积分规则

个人签名:HOLTEK QQ:710536965 ------------------------------------------------------------------------------

29

主题

184

帖子

0

粉丝