搜索
bottom↓
回复: 20

新型的按键扫描程序能不能支持多按键啊

[复制链接]

出0入0汤圆

发表于 2013-6-22 21:20:02 | 显示全部楼层 |阅读模式
在网上论坛经常看到这个新型的按键扫描程序,
新型的按键扫描程序

核心算法:
unsigned char Trg;

unsigned char Release;

unsigned char Cont;

void KeyRead( void )

{

    unsigned char ReadData = PINB^0xff;      // 1  读键值

Trg = ReadData & (ReadData ^ Cont);      // 2  得到按下触发值

Release=(ReadData^Trg^Cont);            //3   得到释放触发值

    Cont = ReadData;                       //4   得到所有未释放的键值

}
(1)       没有按键的时候 ReadData = 0x00;Trg = 0x00;Cont = 0x00;
(2)       第一次PB0按下的情况 ReadData = 0x01;Trg = 0x01;Cont = 0x01;
(3)       PB0按着不松(长按键)的情况 ReadData = 0x01;Trg = 0x00;Cont = 0x01;
(4)       按键松开的情况 ReadData = 0x00;Trg = 0x00;Cont = 0x00;

数码之家贴子在http://bbs.mydigit.cn/read.php?tid=584859,利用状态机思想扫描按键,感觉很有用,就想移植。但是移植过程中就发现问题了:理论是支持多个按键的扫描,但是我实验时怎么就只能实现一个按键的扫描呢?而且有点诡异现象!
我的实验部分代码:
#define        KEY1        =0x01
#define        KEY2        =0x02
#define        KEY3        =0x04
uchar Trg=0,Cont=0;
uchar num;

void keyscan(){                                
        unsigned char ReadData=(P2|0xf8)^0xff;//~(P2|0xf8);//(P2|0xf8)^0xff;//P2^0,1,2组需要处理,其他屏蔽
        Trg=ReadData &(ReadData^Cont);//判断是否点动,异或:不同就1
        Cont=ReadData;//判断是否长按
}
void tiem1(void) interrupt 3{
         keyscan();
        if(Trg&KEY1){               
                num++;
                if(num>15)
                        num=0;
        }
        if(Trg&KEY2){
                num--;
                if(num<1)
                        num=15;
        }
        if(Trg&KEY3){
                num=0;
        }
        display();
    TH1 = 0x63;              //20ms扫描一次
    TL1 = 0xc0;  
}
我的实验结果:
1、         void tiem1(void) interrupt 3{
         keyscan();
        if(Trg&KEY1){               
                num++;
                if(num>15)
                        num=0;
        }
        if(Trg&KEY2){
                num--;
                if(num<1)
                        num=15;
        }
        if(Trg&KEY3){
                num=0;
        }
        display();
    TH1 = 0x63;              //20ms扫描一次
    TL1 = 0xc0;  
}
则只有KEY1起作用,可以短按,长按。其他按键无效。
2、         keyscan();
        if(Trg&KEY2){
        }

        if(Trg&KEY3){
        }
        if(Trg&KEY1){               
        }
则只有KEY2起作用,其他按键无效。
3、keyscan();
        if(Trg&KEY3){
        }

        if(Trg&KEY1){               
        }
        if(Trg&KEY2){
        }
则只有KEY3起作用,其他按键无效。
结论:谁在前,谁起作用,不能多按键扫描。

这就是上面我所说的诡异了。搞了很久都没搞明白我实在是菜啊

请各位亲指点下迷津

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2013-6-22 21:45:59 | 显示全部楼层
行列矩阵要硬件支持才可以多键,要接一堆二极管!

出0入0汤圆

发表于 2013-6-22 22:11:03 | 显示全部楼层
支持4*4键盘,我搭硬件试验过,但这个程序存在问题,如连按键50次会多、少次数,在找办法解决

出0入0汤圆

 楼主| 发表于 2013-6-22 23:37:37 | 显示全部楼层
barryliu 发表于 2013-6-22 21:45
行列矩阵要硬件支持才可以多键,要接一堆二极管!

我看过有人用过这程序去扫描按键,他的是有个按键的

出0入0汤圆

 楼主| 发表于 2013-6-22 23:38:48 | 显示全部楼层
ft_cs 发表于 2013-6-22 22:11
支持4*4键盘,我搭硬件试验过,但这个程序存在问题,如连按键50次会多、少次数,在找办法解决 ...

支持矩阵键盘啊。。。我现在连三个按键都搞不定

出0入0汤圆

发表于 2013-6-23 00:13:33 | 显示全部楼层
用这个程序试试,保证好用,20Ms扫描一次KeyScan()
//按键检测
unsigned char KeyPressDown=0x00;                                  //键按下
unsigned char KeyRelease=0x00;                                        //键弹起
unsigned char LastKey=0x00;                                         

void KeyScan(void)
{
        static unsigned char LastReadKey=0x00;
        unsigned char CurrReadKey;                                 
        unsigned char CurrKey;                                     
        unsigned char KEY_H=0,KEY_L=0;
//读键盘
        P2=0x0f;                                                                        //高四位输出低电平
        KEY_H=P2&0x0f;                                                                //读低四位
        P2=0xf0;                                                                        //低四位输出低电平
        KEY_L=P2&0xf0;                                                                //读高四位
        CurrReadKey=~(KEY_H | KEY_L);                                 //取反

        CurrKey=(CurrReadKey&LastReadKey)|LastKey&(CurrReadKey^LastReadKey);
        //记录按键按下及释放
        KeyPressDown=(~LastKey)&CurrKey;
        KeyRelease=LastKey&(~CurrKey);

        LastReadKey=CurrReadKey;
        LastKey=CurrKey;
}

void KeyPress(void)
{
        switch (KeyPressDown)//根据按下的键散转
          case 0x18:
            //按键1
             break;
         case 0x21:
            //按键2
                .
                .
         case 0x24:
            //按键16
             break;
}

出0入0汤圆

发表于 2013-6-23 09:05:35 来自手机 | 显示全部楼层
4*4键盘,一般单键的多,长短键也可以,多键要加二极管的。话说按键不少了啊!

出0入0汤圆

 楼主| 发表于 2013-6-23 11:17:47 | 显示全部楼层
fiddly 发表于 2013-6-23 09:05
4*4键盘,一般单键的多,长短键也可以,多键要加二极管的。话说按键不少了啊! ...

unsigned char ReadData=(P2|0xf8)^0xff;//~(P2|0xf8);//(P2|0xf8)^0xff;//P2^0,1,2组需要处理,其他屏蔽
我只要三个独立按键

出0入0汤圆

 楼主| 发表于 2013-6-23 13:04:50 | 显示全部楼层
ft_cs 发表于 2013-6-23 00:13
用这个程序试试,保证好用,20Ms扫描一次KeyScan()
//按键检测
unsigned char KeyPressDown=0x00;                                  // ...

P2=0x0f;                                                                        //高四位输出低电平
        KEY_H=P2&0x0f;                                                                //读低四位
        P2=0xf0;                                                                        //低四位输出低电平
        KEY_L=P2&0xf0;                                                                //读高四位
        CurrReadKey=~(KEY_H | KEY_L);                                 //取反
这样折腾,是不是4*4按键啊?
其后的按键出来,真的很复杂。不过,貌似思路跟文中提到的差不多
CurrKey=ReadData
KeyPressDown=Trg
KeyRelease=Release
LastKey=Cont
不过,当我看到switch (KeyPressDown)就恍然大悟,这不是switch(Trg)吗?
既然我的诡异现象是:谁在前,谁起作用
原因其实就是要让三个按键的触发享有相同的优先权,显然,用if是想不通
前些天想过用switch结构,但是自己思维真的拘束的在Trg&KEY上,三个按键没有相同的表达式。
其实,Trg本身就是很好的switch表达式
void tiem1(void) interrupt 3{
        keyscan();
        switch(Trg)
        {        case 0x01:
                        break;
                case 0x02:
                        break;
                case 0x04:
                        break;
                default :break;
        }
        display();
    TH1 = 0x63;              
    TL1 = 0xc0;  
}
问题解决。
弱弱回复说多一句,按操作中的优先级:&>^>|;
感谢启发

出0入0汤圆

发表于 2013-6-23 16:12:22 | 显示全部楼层
试下这个
unsigned char ReadData=(P2^0xff)&0x07;//P2^0,1,2组需要处理,其他屏蔽

出0入0汤圆

 楼主| 发表于 2013-6-23 17:17:44 | 显示全部楼层
Bicycle 发表于 2013-6-23 16:12
试下这个
unsigned char ReadData=(P2^0xff)&0x07;//P2^0,1,2组需要处理,其他屏蔽

问题已经解决,就在上楼。
这个已经在注释里了
unsigned char ReadData=(P2|0xf8)^0xff;//~(P2|0xf8);//(P2|0xf8)^0xff;//P2^0,1,2组需要处理,其他屏蔽

出0入0汤圆

发表于 2013-6-23 22:46:52 | 显示全部楼层
好,MARK,后面也试用下这个程序

出0入0汤圆

发表于 2013-6-25 13:53:16 | 显示全部楼层
Playboy_xixi 发表于 2013-6-23 17:17
问题已经解决,就在上楼。
这个已经在注释里了
unsigned char ReadData=(P2|0xf8)^0xff;//~(P2|0xf8);// ...


矩阵键盘在没有加二极管隔离的情况下是肯定不支持多键同时按下的,这一点根本不需发讨论。
如果两个键或多个键所在的行和列都不同的话是无法识别的,两键同时按下就是多行或多列短路,识别出来会是4个键被按下。
所以程序上只能识别同一行或同一列上的多个键同时按下,而加二极管后可以消除这种短路,于是才能支持既不同行也不同列的多个键同时按下。

出0入0汤圆

发表于 2013-6-25 14:26:09 | 显示全部楼层
barryliu 发表于 2013-6-25 13:53
矩阵键盘在没有加二极管隔离的情况下是肯定不支持多键同时按下的,这一点根本不需发讨论。
如果两个键或 ...

我感觉不是这样吧,我没看上面的程序,但是我感觉应该可以实现没有二极管的情况下识别非同列或者同行的多个按键吧,至少两个应该没有问题吧。

出0入0汤圆

发表于 2013-6-26 06:03:38 | 显示全部楼层
xiaobendan001 发表于 2013-6-25 14:26
我感觉不是这样吧,我没看上面的程序,但是我感觉应该可以实现没有二极管的情况下识别非同列或者同行的多 ...

两个和100个没区别,只要不在同一行也不在同一列上,就会误识别。

出0入0汤圆

发表于 2013-6-26 06:43:33 | 显示全部楼层
只用到短按键和长按键。

出0入0汤圆

发表于 2013-11-2 14:08:28 | 显示全部楼层
还是用不好啊!

出0入0汤圆

 楼主| 发表于 2013-11-10 19:18:55 | 显示全部楼层
Excellence 发表于 2013-6-26 06:43
只用到短按键和长按键。

可以的话,自己研究双击等功能咯

出0入0汤圆

发表于 2014-10-31 17:07:52 | 显示全部楼层
记录一下

出0入0汤圆

发表于 2015-10-19 11:03:27 | 显示全部楼层
先收藏一下,谢谢分享

出0入0汤圆

发表于 2015-11-3 09:21:40 来自手机 | 显示全部楼层
马克一下。。谢谢分享
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-23 18:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表