打印
[8/16-bit MCU]

添加按键处理程序并在LCD上显示

[复制链接]
915|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
仙女山|  楼主 | 2015-12-22 20:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我的是第二批的LPC54100板子,板子上带了一个五位按键,一个复位按键,和两个功能键,一共8个,其中复位键我们不用处理,所以就是7个按键要处理。
#include "key_fun.h"
#include "bsp_key.h"

#define KEY_COUNT                        7
#define KEY0        0x0001
#define KEY1        0x0002
#define KEY2        0x0004
#define KEY3        0x0008
#define KEY4        0x0010
#define KEY5        0x0020
#define KEY6        0x0040

// 需要修改部分
#define button0                 KEY0_IN
#define button1          (KEY1_IN)
#define button2                KEY2_IN
#define button3         KEY3_IN
#define button4         (KEY4_IN)
#define button5         KEY5_IN
#define button6         KEY6_IN

我打算实现按键的长短按和连按的检测,所以需要建立一个按键处理状态机,首先进行初始化

相关帖子

沙发
仙女山|  楼主 | 2015-12-22 20:02 | 只看该作者
#define GetKey0                (button0?0:KEY0)
#define GetKey1                (button1?0:KEY1)
#define GetKey2                (button2?0:KEY2)
#define GetKey3                (button3?0:KEY3)
#define GetKey4                (button4?0:KEY4)
#define GetKey5                (button5?0:KEY5)
#define GetKey6                (button6?0:KEY6)
// 控制按键时长
#define LONG_PRESS_MAX 250 // 20ms*250=5s,长按最大
#define LONG_PRESS 100 // 20ms*100=2s,长按
#define SHORT_PRESS 5 // 20ms*5=100ms,短按
#define MID_PRESS 50 // 20ms*50=1s,连按                第一次开始时间
#define REPEAT_PRESS 25 // 20ms*25=500ms,连按灵敏参数 ,半秒钟触发一次

使用特权

评论回复
板凳
仙女山|  楼主 | 2015-12-22 20:03 | 只看该作者
#define FALSE        false
#define TRUE        true      
//私有变量
unsigned char key_time[KEY_COUNT];
unsigned long io_last,io_now;
//全局变量
unsigned short key_status; // Long[15...8]/Short[7...0]

// 初始化
void key_fun_init(void)
{ unsigned char i;
        //初始化按键I/O口属性
                KEY_Initialize();
        //初始化变量
    io_last=0;
    io_now=0;
    key_status=0;
                for(i=0;i<KEY_COUNT;i++) key_time[i]=0;  
}

使用特权

评论回复
地板
仙女山|  楼主 | 2015-12-22 20:04 | 只看该作者
按键长按,短按和连按的时间在宏定义里面可以修改
接着是按键扫描程序
// 按键处理
void key_scan(void)
{
    //按键端口上拉了,默认是高电平,有按键时变低。这里取反,有按键时变高。
    io_now=0;
          io_now=GetKey0|GetKey1|GetKey2|GetKey3|GetKey4|GetKey5|GetKey6;
                key_status=0;
    // set键只分长按和短按,没有连按
    if ((io_now&KEY0) & (io_last&KEY0))
    {   
        key_time[0]++;
        if (key_time[0]==LONG_PRESS) {key_status|= KEY_SET_LONG;}
        if (key_time[0]>LONG_PRESS) key_time[0] = LONG_PRESS+1;        //只触发一次   
    }

使用特权

评论回复
5
仙女山|  楼主 | 2015-12-22 20:04 | 只看该作者
    else
    {        //按键释放
        if(key_time[0]>SHORT_PRESS)
        {
          if ((key_time[0]<LONG_PRESS))       key_status |= KEY_SET_SHORT;        //短按只在按键释放时响应,且只触发一次,
        }
        key_time[0] = 0;
    }

    // up和down键有连按和短按,没有长按
    if ((io_now&KEY1) & (io_last&KEY1))
    {
        key_time[1]++;
        if (key_time[1]>MID_PRESS)                      //持续按住过程中当时间大于MID_PRESS定义时触发一次短按
        {                              
            key_status |= KEY_UP_SHORT;
            key_time[1] = key_time[1] - REPEAT_PRESS;   //设定出发周期,继续等待下一次触发
        }
    }

使用特权

评论回复
6
仙女山|  楼主 | 2015-12-22 20:05 | 只看该作者
    else
    {
        if (key_time[1]>SHORT_PRESS)
        {                       
            key_status |= KEY_UP_SHORT;            //释放时根据时间触发一次短按
        }
        key_time[1] = 0;                                //只要释放,都要重新计时
    }

    // up和down键有连按和短按,没有长按
    if ((io_now&KEY2) & (io_last&KEY2))
    {
        key_time[2]++;
        if (key_time[2]>MID_PRESS)
        {
            key_status |= KEY_DOWN_SHORT;
            key_time[2] = key_time[2] - REPEAT_PRESS;
        }
    }

使用特权

评论回复
7
仙女山|  楼主 | 2015-12-22 20:06 | 只看该作者
else
    {
        if (key_time[2]>SHORT_PRESS)
        {
            key_status |= KEY_DOWN_SHORT;
        }
        key_time[2] = 0;
    }
               
    // up和down键有连按和短按,没有长按
    if ((io_now&KEY3) & (io_last&KEY3))
    {
        key_time[3]++;
        if (key_time[3]>MID_PRESS)
        {
            key_status |= KEY_LEFT_SHORT;
            key_time[3] = key_time[3] - REPEAT_PRESS;
        }
    }
    else
    {
        if (key_time[3]>SHORT_PRESS)
        {
            key_status |= KEY_LEFT_SHORT;
        }
        key_time[3] = 0;
    }

使用特权

评论回复
8
仙女山|  楼主 | 2015-12-22 20:07 | 只看该作者
    // up和down键有连按和短按,没有长按
    if ((io_now&KEY4) & (io_last&KEY4))
    {
        key_time[4]++;
        if (key_time[4]>MID_PRESS)
        {
            key_status |= KEY_RIGHT_SHORT;
            key_time[4] = key_time[4] - REPEAT_PRESS;
        }
    }
    else
    {
        if (key_time[4]>SHORT_PRESS)
        {
            key_status |= KEY_RIGHT_SHORT;
        }
        key_time[4] = 0;
    }

使用特权

评论回复
9
仙女山|  楼主 | 2015-12-22 20:08 | 只看该作者
    // KEY1键只分长按和短按,没有连按
    if ((io_now&KEY5) & (io_last&KEY5))
    {   
        key_time[5]++;
        if (key_time[5]==LONG_PRESS) {key_status|= KEY_KEY1_LONG;}
        if (key_time[5]>LONG_PRESS) key_time[5] = LONG_PRESS+1;        //只触发一次   
    }
    else
    {        //按键释放
        if(key_time[5]>SHORT_PRESS)
        {
          if ((key_time[5]<LONG_PRESS))       key_status |= KEY_KEY1_SHORT;        //短按只在按键释放时响应,且只触发一次,
        }
        key_time[5] = 0;
    }

使用特权

评论回复
10
仙女山|  楼主 | 2015-12-22 20:08 | 只看该作者
    // KEY2键只分长按和短按,没有连按
    if ((io_now&KEY6) & (io_last&KEY6))
    {   
        key_time[6]++;
        if (key_time[6]==LONG_PRESS) {key_status|= KEY_KEY2_LONG;}
        if (key_time[6]>LONG_PRESS) key_time[6] = LONG_PRESS+1;        //只触发一次   
    }
    else
    {        //按键释放
        if(key_time[6]>SHORT_PRESS)
        {
          if ((key_time[6]<LONG_PRESS))       key_status |= KEY_KEY2_SHORT;        //短按只在按键释放时响应,且只触发一次,
        }
        key_time[6] = 0;
    }               
           // 添加自己对于set_long,set_short,up_short,down_short的处理代码
    // 处理完了不要忘记把相应的值置为FALSE
    io_last = io_now;
}

使用特权

评论回复
11
仙女山|  楼主 | 2015-12-22 20:09 | 只看该作者
在主循环里周期性调用按键扫描函数即可,之后就可以通过判断key_status即可知道是那个或那些按键按下了。
/*        处理完毕,清除标志位 */
void key_flag_clr(void)
{
key_status=0;
}

之后需要清掉key_status。

使用特权

评论回复
12
仙女山|  楼主 | 2015-12-22 20:09 | 只看该作者
主循环
 Lcd7585_write_string(0,7,(char *)"LPC541x Board");  
        Lcd7585_write_string(0,6,(char *)" --by Shower.xu");   
        while(1)
        {   
                delay_xms(15);
                key_scan();
                if(key_status)
                {
                        if(key_status&KEY_SET_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
                        Lcd7585_write_string(12,3,(char *)"o");
                        if(key_status&KEY_UP_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
                        Lcd7585_write_string(12,4,(char *)"^");
                        if(key_status&KEY_DOWN_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
                        Lcd7585_write_string(12,2,(char *)"v");
                        if(key_status&KEY_LEFT_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
                        Lcd7585_write_string(2,3,(char *)"<");
                        if(key_status&KEY_RIGHT_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
                        Lcd7585_write_string(22,3,(char *)">");      

使用特权

评论回复
13
仙女山|  楼主 | 2015-12-22 20:10 | 只看该作者
if(key_status&KEY_KEY1_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
                        Lcd7585_write_string(42,4,(char *)" KEY1 ");        
                        if(key_status&KEY_KEY2_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
                        Lcd7585_write_string(42,2,(char *)" KEY2 ");        
                        key_flag_clr();
                }
        }

使用特权

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

本版积分规则

36

主题

340

帖子

2

粉丝