打印

如何实现一个按键多种功能?

[复制链接]
9001|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
沙发
hotpower| | 2010-6-22 07:22 | 只看该作者
板凳
ayb_ice| | 2010-6-22 09:23 | 只看该作者
同一按键在不同状态下功能不同

使用特权

评论回复
地板
dtmcp| | 2010-6-22 09:45 | 只看该作者
可以设个定时器,基于时间的长按或短按

使用特权

评论回复
5
hgjinwei| | 2010-6-22 12:25 | 只看该作者
楼主想想发电报的过程,应该可以搞定了。

使用特权

评论回复
6
ningling_21| | 2010-6-22 13:11 | 只看该作者
状态机

使用特权

评论回复
7
一棵小草| | 2010-6-22 13:14 | 只看该作者
我一般用一个变量来做计数的。
举例:
sbit        key  = P3^7;
unsigned      char       keycount;      //初始化为0

//按键扫描
if(key ==0)
{
          //消抖部分不写出来了
           if(++keycount==4)keycount=0;     //这里只举例3个功能
}

//按键处理
switch   keycount
{
         case   1:  //------功能1;break;
         case   2:  //------功能2;break;
         case   3:  //------功能3;break;
         default:   //------功能0;break;      //如果没有功能0就空着吧。
}

使用特权

评论回复
8
haotz| | 2010-6-22 15:19 | 只看该作者
只能 TD或 CD ,空分肯定不行

使用特权

评论回复
9
johnlin519| | 2010-6-22 15:55 | 只看该作者
状态机是正解~

使用特权

评论回复
10
zhiyonghe| | 2010-6-22 17:21 | 只看该作者
/**********************************
**                              
**
**文件说明:
    首先按键有四个,单线接入,没有用矩阵.   
    按键使用状态机,三个状态   
    所有按键返回KeyDown值.不返回KeyUp值.
    支持部分按键有连发功能.
        向上键,向下键支持,
        确认键和取消键不支持

/**********************************
#include "config.h"
  
#define     KEY1_IOPIN          (1<<13)
#define     KEY2_IOPIN          (1<<15)
#define     KEY3_IOPIN          (1<<7)
#define     KEY4_IOPIN          (1<<6)
#define     KEY_EINT2_IOPIN     (1<<14)

void KeySysInit(void)
{
    PINSEL0  = PINSEL0 & 0x33FF0FFF;    //设置P0.6 7 13 15为GPIO

    IO0DIR  &=  ~(  KEY1_IOPIN| \
                    KEY2_IOPIN| \
                    KEY3_IOPIN| \
                    KEY4_IOPIN  );      //配置为输入
                    
                    
    IO0SET   =   (  KEY1_IOPIN| \
                    KEY2_IOPIN| \
                    KEY3_IOPIN| \
                    KEY4_IOPIN  );
}


INT8U GetKeyCode(void)
{
    if( !(IO0PIN & KEY1_IOPIN) )return 1;
    if( !(IO0PIN & KEY2_IOPIN) )return 2;
    if( !(IO0PIN & KEY3_IOPIN) )return 3;
    if( !(IO0PIN & KEY4_IOPIN) )return 4;   
    return 0;
}


#define     KEY_SERIES_FLAG     30      //按键连发开始所需时间长度
#define     KEY_SERIES_DELAY    4       //按键连发的时间间隔长度

//使用状态机的方法来处理按键
//支持部分按键连发
INT8U GetKey()
{
    static INT8U KeyState = 0;      //按键状态
    static INT8U KeyPrev  = 0;      //上一次按键
    static INT8U KeyDelay = 0;      //按键连发时间  
    static BOOL  bKeySeries= 0;     //标志连发开始
   
    INT8U KeyPress  = 0;            //按键值
    INT8U KeyReturn = 0;            //按键返回值.
   
   
    KeyPress = GetKeyCode();
   
    switch(KeyState)
    {
        //按键初始态
        case 0:
            if( KeyPress )
            {
                KeyState = 1;
                KeyPrev  = KeyPress;
            }
            break;
            
        //按键确认态   
        case 1:
            if( KeyPress )
            {
                //与上次按键不同,是乱码
                if(KeyPrev  != KeyPress)
                {
                    KeyState  = 0;
                    KeyReturn = 0;
                }
                else
                {
                    KeyState  = 2;
                    KeyReturn = KeyPrev;
                }
            }
            else
            {//按键抬起,是抖动,不响应按键
                KeyState = 0;
            }
            break;
        
        //按键释放,返回初始状态
        case 2:
            if(!KeyPress )
            {
                KeyState   = 0;
                KeyDelay   = 0;
                bKeySeries = 0;
            }
            //按键连发程序
            else if( (KeyPress==1) || (KeyPress==2) )//这些按键支持连发...
            {
                KeyDelay++;
                if(KeyDelay>KEY_SERIES_FLAG)
                {
                    bKeySeries = 1; //启动按键连发
                }               
                if( (bKeySeries==1) && (KeyDelay>KEY_SERIES_DELAY) )
                {
                    KeyDelay  = 0;
                    KeyReturn = KeyPrev;
                }
               
            }
            break;
    }
   
    return KeyReturn;
}



#include "MENU.H"

void DealKey(void)
{
    INT8U KeyTmp;
    KeyTmp = GetKey();
   
    switch(KeyTmp)
    {
        case 1: Menu_Next();    break;
        case 2: Menu_Prev();    break;
        case 3: Menu_Enter();   break;
        case 4: Menu_Esc();     break;
    }
}

//文件结束

//============================================

使用特权

评论回复
11
流行音乐| | 2010-6-22 17:25 | 只看该作者
只要是程序,就有状态机。

使用特权

评论回复
12
strang| | 2010-6-22 19:47 | 只看该作者
请看附件!

一键多功能按键识别技术.zip

24.87 KB

使用特权

评论回复
13
lphbkj| | 2010-6-25 21:16 | 只看该作者
同意7楼的

使用特权

评论回复
14
xw802| | 2010-8-18 11:19 | 只看该作者
7楼的方法最通用,定义一个自加变量,每按下一个键就实现一种功能

使用特权

评论回复
15
xialvfire| | 2010-8-18 16:36 | 只看该作者
状态机制是 正解,不同时候触发按键设置不同的标志位,然后再判断状态标志位!

使用特权

评论回复
16
海2000| | 2014-2-17 11:00 | 只看该作者
你好,我在做4*4多功能按键程序时,遇到点问题,想请教你一下,不知道方便不?QQ1024829053

使用特权

评论回复
17
海2000| | 2014-2-17 11:01 | 只看该作者
按键功能图解

多功能小键盘图解.png (34.14 KB )

多功能小键盘图解.png

使用特权

评论回复
18
J冷风J| | 2015-5-17 18:11 | 只看该作者
本帖最后由 J冷风J 于 2015-5-17 18:14 编辑
一棵小草 发表于 2010-6-22 13:14
我一般用一个变量来做计数的。
举例:
sbit        key  = P3^7;

我有个程序你能帮我看下吗#include<reg51.h>
sbit D3=P3^7;        //位定义控制开关S2的P3.7口
int m,n;

void main()
{
        m=0;                //给变量赋初值
        P1=0xfe;        //初始状态P1.0二极管亮

            while(1)
        {
                if (D3==0)
                    m++;
                    n=m%4;                 //取余来选择哪个二极管亮
                switch(n)
                {
                        case 0: P1=0xfe;    //按4k次P1.0二极管亮
                        case 1: P1=0xfd;        //按4k+1次P1.1二极管亮
                        case 2: P1=0xfc;        //按4k+2次P1.2二极管亮
                        case 3: P1=0xfb;        //按4k+3次P1.3二极管亮
                }
        }
}


使用特权

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

本版积分规则

0

主题

58

帖子

1

粉丝