OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 12154|回复: 37

自己应用中用到的按键扫描方法,分享给大家。

[复制链接]

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
发表于 2015-12-8 10:19:40 | 显示全部楼层 |阅读模式
经常看大家讨论按键扫描的问题,自己最近刚好同时用到独立按键和矩阵按键,整理了这两种按键的扫描程序。很久以前,在网上看到一篇“新型按键扫描方法”的文章,参考稍做修改用来按键扫描,发现效果不错,工作中使用稳定可靠,方便移植,之前一直用独立按键,近日刚好弄到矩阵按键,因此整理分享给大家。整理成模块,只需要添加你需要的键值就行了。它可以实现你想得到的键值,发挥你的想象力,只要你想得到,就能做到。同时感谢网友发表的那篇文章。

//模板
  typedef struct
{
    u8 getKeyVal :7;
    u8 fkeyLock :1;
}BUTTON_TypeDef;
           
u8 scan_keypad(BUTTON_TypeDef *p)
{
        static u8 keyValue,tmp_keyValue,keyTrigger,keyKeep;
        static u16 keyDelayNum,keyDelayNumValue;
        keyValue=SINGLE_KEY_INPUT;//1,得到按键输入状态,有按键的位为1,无按键为0
        while(1)
        {    
                if(keyValue!=tmp_keyValue)
                {  
                        keyDelayNumValue=10; //2,按键去抖节拍数,根据要求修改
                        tmp_keyValue=keyValue;
                        keyDelayNum=0;
                        keyTrigger=0;
                        keyKeep=0;
                        break;
                }
                else
                {  
                        if(keyDelayNum<keyDelayNumValue)
                        {   
                                keyDelayNum++;
                                break;
                        } 
                        keyTrigger=keyValue&(keyValue^keyKeep);
                        keyKeep=keyValue; 
                }
                if(keyValue)
                {      
                        if(!p->fkeyLock)
                        {
                                if(keyTrigger)
                                {
                                        
                                        //3,处理短按,有效键值按下只进来一次,必须释放后再按再次进来
                                        //如果某个按键需要长按或者连按,在这里设置进入4的节拍数?
                                                                                    
                        
                                }
                                else
                                {
                                        
                                              
                                        //4,处理长按或者连按
                                            
                                }
                        } 
                
                }
                else
                {   
                        //5,处理释放后才动作的键值或者双击,多击等功能。
                                     
                }   
                break;         
        }
        return   p->getKeyVal;   
        



keypad.zip

2.96 KB, 下载次数: 1088

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

130

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
373
金钱
373
注册时间
2015-3-7
在线时间
43 小时
发表于 2015-12-8 10:23:23 | 显示全部楼层
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2015-12-8 10:29:40 | 显示全部楼层
谢谢分享按键扫描方法.....
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-8 10:32:54 | 显示全部楼层
压缩文件里面有独立按键和矩阵按键扫描的例程,欢迎下载应用,望诸位大神多提意见,不断完善。
回复 支持 反对

使用道具 举报

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
发表于 2015-12-8 12:21:51 | 显示全部楼层
谢谢分享!有空看看
我的博客:http://blog.csdn.net/itdo_just
回复 支持 反对

使用道具 举报

13

主题

296

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2066
金钱
2066
注册时间
2012-5-26
在线时间
291 小时
发表于 2015-12-8 12:25:58 | 显示全部楼层
谢谢分享,留着备用
活着才是王道!健康是一切的前提!
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-21 19:48:33 | 显示全部楼层
回复【2楼】Mcu_learning:
---------------------------------
谢谢分享!能否给个C51程序,谢谢!
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-21 20:57:41 | 显示全部楼层
回复【7楼】zlkj:
---------------------------------
有什么区别么?51的 连初始化都不用,就做个宏定义,把每个按键放入变量的位就行了,扫描函数直接可以用。
回复 支持 反对

使用道具 举报

70

主题

6761

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13102
金钱
13102
注册时间
2012-11-26
在线时间
3811 小时
发表于 2015-12-21 21:11:46 | 显示全部楼层
谢谢分享,留着备用
学无止境
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2015-12-21 22:59:07 | 显示全部楼层
谢谢分享....
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

14

主题

97

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
204
金钱
204
注册时间
2014-12-16
在线时间
10 小时
发表于 2015-12-22 08:22:18 | 显示全部楼层
感谢分享, 学习一下
回复 支持 反对

使用道具 举报

11

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
159
金钱
159
注册时间
2015-11-2
在线时间
17 小时
发表于 2015-12-22 09:23:13 | 显示全部楼层
3Q. mark this topic.
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-23 10:58:05 | 显示全部楼层
回复【12楼】xupt_ln:
---------------------------------
LZ你好!
请求给个C51程序,感谢!!!!!!!!
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-23 12:07:31 | 显示全部楼层
回复【13楼】zlkj:
---------------------------------

#ifndef __KEYPAD_H
#define __KEYPAD_H 
 //假设独立按键2个,从低位开始排列,key2,key1
#define SINGLE_KEY_INPUT       ((((P0^2<<1)|P0^1))&0x03)^0x03)

//按键状态,有组合状态
#define KEY_STATUS1    0x01   //key1按下状态
#define KEY_STATUS2    0x02   //key2按下状态
#define KEY_STATUS3    0x03   //key1,key2同时按下状态
//根据应用设定键值个数和键值
#define S1                   1    //key1短按键值
#define S2                   2    //这个用作key2的释放后键值
#define S3                   3    //组合键值
#define S1_3S                4    //key1长按3S键值





#define MASK_KEY         0x40 
#define LOCK_KEY        (MASK_KEY-1) 
#define CONV_KEY        (MASK_KEY-2) 
#define NONE_KEY         0 

typedef struct
{
    u8 getKeyVal:7;
    u8 fkeyLock:1;
}BUTTON_TypeDef;

extern BUTTON_TypeDef keypad;

void init_keypad(void);
u8 scan_keypad(BUTTON_TypeDef *p);
#endif


#include "keypad.h"
BUTTON_TypeDef keypad;

void init_keypad()
{
    


    

}
/*
scan single IO keypad

*/
u8 scan_keypad1(BUTTON_TypeDef *p)
{
        static u8 keyValue,tmp_keyValue,keyTrigger,keyKeep;
        static u16 keyDelayNum,keyDelayNumValue;
        keyValue=SINGLE_KEY_INPUT;
        while(1)
        {    
                if(keyValue!=tmp_keyValue)
                {  
                        keyDelayNumValue=10;
                        tmp_keyValue=keyValue;
                        keyDelayNum=0;
                        keyTrigger=0;
                        keyKeep=0;
                        break;
                }
                else
                {  
                        if(keyDelayNum<keyDelayNumValue)
                        {   
                                keyDelayNum++;
                                break;
                        } 
                        keyTrigger=keyValue&(keyValue^keyKeep);
                        keyKeep=keyValue; 
                }
                if(keyValue)
                {      
                        if(!p->fkeyLock)
                        {
                                if(keyTrigger)
                                {
                                        
                                        switch(keyValue)
                                        {
                                            case KEY_STATUS1:
                                                                          p->getKeyVal=S1;//key1
                                                                          keyDelayNum=0;
                                                                          keyDelayNumValue=600;

                                            break;
                                            case KEY_STATUS2:
                                                                        p->getKeyVal=S2|MASK_KEY;//key2

                                            break;
                                            case KEY_STATUS3:
                                                                        p->getKeyVal=S3; //组合键
                                            break;
                                            default:
                                                                        p->fkeyLock=TRUE;
                                                                        p->getKeyVal=MASK_KEY;
                                            break;
                                        }
                                                                                    
                        
                                }
                                else
                                {
                                        
                                              
                                        switch(keyValue)
                                        {
                                            case KEY_STATUS1:
                                                                    keyDelayNum=0;
                                                                    keyDelayNumValue=~0u;
                                                                    p->getKeyVal=S1_3S;  //S1的长按键
                                            break;
                                        }        
                                            
                                }
                        } 
                
                }
                else
                {   
                        p->fkeyLock=FALSE; 
                        if(p->getKeyVal&MASK_KEY)
                             p->getKeyVal7&=~MASK_KEY;//释放后得到的键值
                        else
                            p->getKeyVal=NONE_KEY;
                                     
                }   
                break;         
        }
        return   p->getKeyVal;   
        
}
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-23 13:46:51 | 显示全部楼层
回复【14楼】TinyBoy:
---------------------------------
非常感谢!再请教C51矩阵键盘行列翻转扫描及双击程序。
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-23 14:02:09 | 显示全部楼层
回复【15楼】zlkj:
---------------------------------
 自己写吧,稍作修改就行了,种种变化,各尽其用。
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-23 14:10:03 | 显示全部楼层
回复【16楼】TinyBoy:
---------------------------------
为了学习多谢指点!
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-23 19:29:20 | 显示全部楼层
回复【17楼】zlkj:
---------------------------------
   static u8 c,keyValue,tmp_keyValue,keyTrigger,keyKeep;
        static u8 keyDelayNum,keyDelayNumValue,fkeyMatrix;
        while(1)
        {    
                if(fkeyMatrix)
                {


                    c|=(I0_STA&0xf0)//1,得到行或者列的状态
                    //行列状态转换
                    fkeyMatrix=FALSE;
                }
                else
                {
                     c=I0_STA&0x0f//1,得到行或者列的状态
                    //行列状态转换,第一次扫描,直接跳出
                    fkeyMatrix=TRUE;
                    break;
                }
                keyValue=c^0xff;//1, 2次扫描得到键盘扫描状态
行列反转扫描,扫描状态如此扫描就行了,因为2次得到扫描状态,你可以把祛抖计数设置小一些。
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-23 20:17:09 | 显示全部楼层
回复【18楼】TinyBoy:
---------------------------------
感谢你的回复!
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-24 19:29:29 | 显示全部楼层
回复【14楼】TinyBoy:
---------------------------------
我用proteus仿真怎么没反应?请教!
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-24 21:36:24 | 显示全部楼层
回复【20楼】zlkj:
---------------------------------
我一般都不仿真,直接烧进去运行看效果。
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-26 19:16:01 | 显示全部楼层
矩阵键盘怎么没反应?
回复 支持 反对

使用道具 举报

344

主题

1464

帖子

12

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
8045
金钱
8045
注册时间
2015-10-15
在线时间
2907 小时
发表于 2015-12-26 19:24:28 | 显示全部楼层
@@正点原子
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

344

主题

1464

帖子

12

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
8045
金钱
8045
注册时间
2015-10-15
在线时间
2907 小时
发表于 2015-12-26 19:24:40 | 显示全部楼层
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

344

主题

1464

帖子

12

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
8045
金钱
8045
注册时间
2015-10-15
在线时间
2907 小时
发表于 2015-12-26 19:24:57 | 显示全部楼层
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-26 19:37:38 | 显示全部楼层
zlkj 发表于 2015-12-26 19:16
矩阵键盘怎么没反应?

独立按键弄过了可以了?矩阵的应该是在按键状态那里没得到吧?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165516
金钱
165516
注册时间
2010-12-1
在线时间
2116 小时
发表于 2015-12-26 19:48:11 | 显示全部楼层
谢谢分享....
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-26 20:04:33 | 显示全部楼层
TinyBoy 发表于 2015-12-26 19:37
独立按键弄过了可以了?矩阵的应该是在按键状态那里没得到吧?

这几天一直学习你的程序,还是没搞明白,请教!
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-26 20:14:25 | 显示全部楼层
zlkj 发表于 2015-12-26 20:04
这几天一直学习你的程序,还是没搞明白,请教!

确定行列在高4位还是低4位,然后根据硬件确定16键值的状态。
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-26 20:24:34 | 显示全部楼层
TinyBoy 发表于 2015-12-26 20:14
确定行列在高4位还是低4位,然后根据硬件确定16键值的状态。

还是给个程序吧!
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-26 20:38:35 | 显示全部楼层
zlkj 发表于 2015-12-26 20:24
还是给个程序吧!

51的我没有,矩阵按键行列转换扫描很多例子,你看人家怎样得到按键状态的就行 了。
回复 支持 反对

使用道具 举报

32

主题

93

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4079
金钱
4079
注册时间
2015-12-21
在线时间
891 小时
发表于 2015-12-26 22:56:02 | 显示全部楼层
TinyBoy 发表于 2015-12-26 20:38
51的我没有,矩阵按键行列转换扫描很多例子,你看人家怎样得到按键状态的就行 了。

为什么长按或者连按无法停止?按键抬起仍继续循环?
回复 支持 反对

使用道具 举报

10

主题

561

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1822
金钱
1822
注册时间
2014-6-27
在线时间
978 小时
 楼主| 发表于 2015-12-26 23:27:47 | 显示全部楼层
zlkj 发表于 2015-12-26 22:56
为什么长按或者连按无法停止?按键抬起仍继续循环?

你处理完按键,清键值了?
回复 支持 反对

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-12-27 13:42:27 | 显示全部楼层
谢谢分享,以后备用。。嘿嘿
回复 支持 反对

使用道具 举报

10

主题

81

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1502
金钱
1502
注册时间
2013-8-28
在线时间
28 小时
发表于 2015-12-27 13:44:11 | 显示全部楼层
mark mark mark
回复 支持 反对

使用道具 举报

0

主题

24

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
483
金钱
483
注册时间
2014-2-9
在线时间
91 小时
发表于 2016-7-8 15:11:54 | 显示全部楼层
谢谢分享!
回复 支持 反对

使用道具 举报

20

主题

138

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
346
金钱
346
注册时间
2012-10-11
在线时间
136 小时
发表于 2016-7-9 13:50:44 | 显示全部楼层
谢谢楼主分享!
回复 支持 反对

使用道具 举报

0

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
78
金钱
78
注册时间
2016-9-26
在线时间
22 小时
发表于 2016-11-2 13:54:31 | 显示全部楼层
谢谢分享。mark
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-24 17:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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