发新帖我要提问
123
返回列表
打印

按键扫描程序曾让多少人都头疼过,肯多很多人都曾遇到过

[复制链接]
楼主: 电子三极管
手机看帖
扫描二维码
随时随地手机跟帖
41
推荐几个外国网站

未命名.JPG (5.28 KB )

未命名.JPG

使用特权

评论回复
42
tangxiaoxiao| | 2010-7-22 17:17 | 只看该作者

使用特权

评论回复
43
欧阳青云| | 2010-7-22 20:56 | 只看该作者
键盘监控程序设计方法中有一种叫状态矩阵法有谁知道是怎么回事吗?

使用特权

评论回复
44
汪道辉| | 2010-7-25 10:17 | 只看该作者
这是较多接口共同工作时时序安排的典型问题。这也是由于各种硬件部分工作可以同时进行,而软件(在唯一CPU的条件下)只能够逐条指令执行而引出的问题。原则仅一个,即将所有硬件、软件的时序逐个安排,将所有硬件、软件的工作过程有机地切分成其功能不受影响的一小段、一小段,再安排进程在所有的“一小段”-“一小段”之间巧妙切换,即总的思路是“切分”和“切换”有机的统一。

使用特权

评论回复
45
nayaix| | 2010-7-25 11:09 | 只看该作者
学习了

使用特权

评论回复
46
梅开二度| | 2010-7-25 13:27 | 只看该作者
提起按键程序,我坚决支持所长的,你若将所长的程序读懂,我读了他的程序按照他的框架写了一个,感觉挺好用。
//        if( ( sKeyProce.KeyVal != 0x1f ) || ( sKeyProce.KeyVal != sKeyProce.KeyLastTime ) ){                //有键按下,处理
                keycompare1 = sKeyProce.KeyLastTime & sKeyProce.KeyProcBit;        //上次按键位的按键状态
                keycompare2 = sKeyProce.KeyVal & sKeyProce.KeyProcBit;                //当前按键位的按键状态
                switch ( sKeyProce.keyTask ){
                        case Idle:                switch ( KeyState() ){
                                                                case keypushmove:        sKeyProce.keyTask = pushdelay;        //按键按下,转入按键延时判断
                                                                                                        break;
                                                                case keypopmove:        sKeyProce.keyTask = popdelay;
                                                                                                        break;
                                                                case keynomove:                sKeyProce.keyTask = Idle;        //按键无动作,转入空闲状态
                                                                                                        break;
                                                                default:                        break;
                                                        }
                                                        break;
                        case pushdelay:        //if( ( sKeyProce.KeyLastTime & sKeyProce.KeyProcBit ) == ( sKeyProce.KeyVal & sKeyProce.KeyProcBit ) ){
                                                        if( keycompare1 == keycompare2 ){        //两次状态相同,按键有效
                                                                sKeyProce.keyTask = pushcheck;
                                                        }else{
                                                                sKeyProce.keyTask = Idle;                //否则,为抖动,推出按键处理
                                                        }
                                                        break;
                        case popdelay:        //if( ( sKeyProce.KeyLastTime & sKeyProce.KeyProcBit ) == ( sKeyProce.KeyVal & sKeyProce.KeyProcBit ) ){
                                                        if( keycompare1 == keycompare2 ){
                                                                sKeyProce.keyTask = popcheck;
                                                        }else{
                                                                sKeyProce.keyTask = Idle;
                                                        }
                                                        break;
                        case pushcheck:        //if( ( sKeyProce.KeyLastTime & sKeyProce.KeyProcBit ) == ( sKeyProce.KeyVal & sKeyProce.KeyProcBit ) ){
                                                        if( keycompare1 == keycompare2 ){                //状态继续相同,按键有效,压入按键信息
                                                                PushMsg( sKeyProce.KeyProcBit );        //按键位       
                                                                PushMsg( pushdown );                                //按键状态
                                                        }
                                                        sKeyProce.keyTask = Idle;        //一个完整的按键处理完毕,转入空闲状态
                                                        break;
                        case popcheck:        //if( ( sKeyProce.KeyLastTime & sKeyProce.KeyProcBit ) == ( sKeyProce.KeyVal & sKeyProce.KeyProcBit ) ){
                                                        if( keycompare1 == keycompare2 ){       
                                                                PushMsg( sKeyProce.KeyProcBit );
                                                                PushMsg( popup );
                                                        }
                                                        sKeyProce.keyTask = Idle;
                                                        break;
                        }

使用特权

评论回复
47
aceice| | 2010-7-26 08:47 | 只看该作者
......终于有我能插上嘴的话题了
开定时器扫描......

使用特权

评论回复
48
huangqi412| | 2010-7-26 09:28 | 只看该作者
;P 公车男,别憋坏了

使用特权

评论回复
49
zljzlj| | 2010-7-26 14:31 | 只看该作者
又是一个教科书的受害者!

使用特权

评论回复
50
yayubin| | 2010-7-26 15:29 | 只看该作者
不用定时器也不用等待
uchar key(void)
   {
     static uchar time=0;
     uchar key;
     key=0;
     if(KEY==0)   //按下
         {
           time++;
           if(time>50) //去科
              {
                KEY=1;
                time=0;
              }
           }
    else
            {
              time=0;
             }
    return key;//返回按扭
     }

使用特权

评论回复
51
highgear| | 2010-7-26 21:55 | 只看该作者
按键检测已经被讨论很多次了。我给出一个曾在 PK 中作的简单的按键处理程序, 使用了定时中断和状态机, 是一个基本上独立而通用的处理程序, 供大家参考。

#define TICK 20         //定时中断间隔时间
#define GetTickCount(t) ((t)/TICK)    //来自 windows API 的函数

struct KeyStatus
{
    char key;
    char pressedKey;
    int keyState;
    int keyTimer;
    char keyEventHandled;
}
m_KeyStatus;

//下面的代码在中断里调用。初始按下后 2 秒后再次发出按下信号, 以后每一秒发一次信号。
void DetectKeyPress()  {
    DetectKeyInput();    //扫描键盘, 并把键码放入 pressedKey 中
    switch (m_KeyStatus.keyState) {
        case 0:
           if (m_KeyStatus.pressedKey != NOKEY)
                m_KeyStatus.keyState++; //去抖动
            break;
        case 1:   
            if (m_KeyStatus.pressedKey == NOKEY)
                m_KeyStatus.keyState--;
            else {
                m_KeyStatus.key = m_KeyStatus.pressedKey;
                m_KeyStatus.keyEventHandled = false;     //允许处理按键事件。
                m_KeyStatus.keyTimer = GetTickCount(2000);                    //2 seconds
                m_KeyStatus.keyState++;
            }
            break;
        case 2:
            if (m_KeyStatus.key != m_KeyStatus.pressedKey) {
                m_KeyStatus.keyState++;   //按键放开或者有另一个按键
            }
            else {
                if (--m_KeyStatus.keyTimer == 0) {
                    m_KeyStatus.keyTimer = GetTickCount(1000);                // 1 second
                    m_KeyStatus.keyEventHandled = false;   //允许处理按键事件。
                }
            }
            break;
      case 3:
            m_KeyStatus.key = NOKEY;
            m_KeyStatus.keyEventHandled = false;
            m_KeyStatus.keyState = 0;
            break;
        default:
            m_KeyStatus.keyState = 0;
     }
}

在其他程序中处理按键:
   if (m_KeyStatus.key != NOKEY && !m_KeyStatus.keyEventHandled) {
       dosometing();   //处理
       m_KeyStatus.keyEventHandled = true;   //处理结束
   }

如果使用函数指针来处理按键按下, 则更类似事件处理(handle event)。不过,在小项目中就没有这种必要了。

使用特权

评论回复
52
WXJPCY888| | 2012-12-14 16:58 | 只看该作者
经典!

使用特权

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

本版积分规则