• 按键扫描之精妙一谈(原创)


    #define KEY0  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键0
    #define KEY1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键1
    #define KEY2  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)//读取按键2 
    #define KEY3  GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键3(WK_UP) 
     
     
    #define KEY_UP 4
    #define KEY_LEFT3
    #define KEY_DOWN2
    #define KEY_RIGHT1
     
    void KEY_Init(void);//IO初始化
    u8 KEY_Scan(u8);  //按键扫描函数
    //按键处理函数
    //返回按键值
    //mode:0,不支持连续按;1,支持连续按;
    //0,没有任何按键按下
    //1,KEY0按下
    //2,KEY1按下
    //3,KEY2按下 
    //4,KEY3按下 WK_UP
    //注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
    u8 KEY_Scan(u8 mode)
    static u8 key_up=1;//按键按松开标志
    if(mode)key_up=1;  //支持连按  
    if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))
    {
    delay_ms(10);//去抖动 
    key_up=0;
    if(KEY0==0)return 1;
    else if(KEY1==0)return 2;
    else if(KEY2==0)return 3;
    else if(KEY3==1)return 4;
    }else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==0)key_up=1;     
     return 0;// 无按键按下
    }
    函数解读:
    一、mode=0时,按键不支持连按,程序运行过程,主函数中,按键扫描,首先默认为key_up=1,因为从开机,到函数运行速度是极快的,因此会扫描到无按键按下。当然,有一种特殊的情况是,在起机时,就按下按键,此时key_up=0,估计少有人去做这么蛋疼的事吧!
    一切准备就绪,程序开始运行,如有按键按下,执行到if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))
    此时,key_up=0,函数返回一个u8型数(0||1||2||3||4),如按键不松开,key_up=0,if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))语句永远不会执行,只有按键松开,执行else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==0)key_up=1,因此实现了按键不连按的效果!当然,此时,或许会有人想,如果,我按一下键,赶紧再按一下,不就永远不会执行if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))里的语句了么,我想说的是,你多虑了,我现在所用的是芯片是72MHZ的,代码执行的间距仅仅几毫秒,人的反应速度还没那么快呢,(注:一般条件下,反应时间约为0.1~0.5 s。对于复杂的选择性反应时间达1~3 s,要进行复杂判断和认识的反应时间平均达3~5 s,具体的带有判别的反应时间t可用下式求得: t = k log2 (n+1)   式中,k为常数;n为等概率出现的选择对象数;(n+1)是考虑判明是否出现刺激。)即是低一点的芯片也是没问题的。
    二、mode=1时,初始化和mode=0是一样,上面提到,在这里就不再说了,直接看代码,函数在主函数中循环,若有按键按下,运行if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1)),此时key_up=0;不丢开按键,主函数循环到按键扫面函数,执行if(mode)key_up=1;之后,若有按键按下,当然可以运行if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1))里的语句了。至此,实现了连续按键。
    三、这个函数的封装性极强,换句话说,即是不懂这个函数里的意思,也可以直接拿来运用,当然函数应当这样描述:
    //按键处理函数
    //返回按键值
    //mode:0,不支持连续按;1,支持连续按;
    //0,没有任何按键按下
    //1,KEY0按下
    //2,KEY1按下
    //3,KEY2按下 
    //4,KEY3按下 WK_UP
    //注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!!
    u8 t;
    t=KEY_Scan(0);
    switch(t)
    {
       case 1:
       case 2:
       case 3:
       case 4:
    }
    函数的整体设计确实很吸引人,如果将函数的扫描放在中断里,将大大节省内存,从而可以提高程序运行速率!
        在这儿不得不再次提到一些高级语言,比如C#,VB,Java等等,个人觉得这些高级语言也许正和上面的这个函数有点相像,封装性太强,尤其C#,感觉一种很飘渺的感觉,说实在的起初还可以,时间久了便腻了!我觉得编程人员不是为编程而编程,而是从编程中去寻找乐趣,寻求一种自由!
        所以,正如这个函数,如果只是调用,太简单了,但是如果你了解了这个的设计过程,那么你就是成功地!当然,若想获得更好,懂得底层驱动,甚至,芯片的驱动原理,呵呵,便最好不过了!
        《易经》:“易有太极,是生两仪两仪四象,四象生八卦。”孔颖达疏:“太极谓天地未分之前,元气混而为一,即是太初、太一也。”
         由于时间仓促及水平有限,难免有些差错和不足,希望读者多多指教!
         高手勿喷,在此谢过代码的设计者!
  • 相关阅读:
    还需要做恰当的解读,此时你可能需要一些书:
    创业公司的架构演进史
    任务调度平台Cuckoo-Schedule
    ORACLE中死锁
    Action的模型绑定
    三次握手、四次握手、backlog
    Django框架
    扩展BootstrapTable的treegrid功能
    Identity Service
    Linux权限
  • 原文地址:https://www.cnblogs.com/skl374199080/p/3108238.html
Copyright © 2020-2023  润新知