单片机学习小组
直播中

贾永世

7年用户 1775经验值
私信 关注

求大佬分享一个堵塞式按键消抖程序

求大佬分享一个堵塞式按键消抖程序

回帖(1)

孙秀英

2022-1-17 14:49:53
堵塞式按键消抖
如下是一个最基本的堵塞式按键程序:


       
        ***it K1 = P1^0;
        ***it K1 = P1^1;
        ***it K1 = P1^2;
        ***it K1 = P1^3;
        #define KEY_VALUE_NULL        0X00
        #define KEY_VALUE_1                0X01
        #define KEY_VALUE_1                0X02
        #define KEY_VALUE_1                0X04
        #define KEY_VALUE_1                0X08
       
        void delay_ms(unsigned char xms)
        {
                unsigned char i,j;
                for(i = xms;i > 0;i--){
                        for(j = 110;j > 0;j--);       
                }
        }
        unsigned char KeyScan(void)
        {
                unsigned char temp = KEY_VALUE_NULL;
                if(K1 == 0){
                        delay_ms(20);
                        if(K1 == 0){
                                temp = KEY_VALUE_1;
                        }
                }
                if(K2 == 0){
                        delay_ms(20);
                        if(K1 == 0){
                                temp = KEY_VALUE_2;
                        }
                }
                if(K3 == 0){
                        delay_ms(20);
                        if(K1 == 0){
                                temp = KEY_VALUE_3;
                        }
                }
                if(K4 == 0){
                        delay_ms(20);
                        if(K1 == 0){
                                temp = KEY_VALUE_4;
                        }
                }
                return temp;
        }
        void main(void)
        {
                unsigned char keyValue = 0;
                while(1)
                {
                        keyValue = KeyScan();
                        if(keyValue == KEY_VALUE_1){
                                //按键1按下执行代码段
                        }
                        if(keyValue == KEY_VALUE_2){
                                //按键2按下执行代码段
                        }
                        if(keyValue == KEY_VALUE_3){
                                //按键3按下执行代码段
                        }
                        if(keyValue == KEY_VALUE_4){
                                //按键4按下执行代码段
                        }
                }
        }


该代码具有堵塞式按键的通病,那就是当按键按下后,所有的CPU时间都用来空跑,对于实时性高的任务,这20ms消抖会带来很多灾难性后果。20ms够我们跑很大量级的指令数了。我们怎么不使用delay来完成按键消抖呢?


时基法编程之按键消抖
如下是一个最基本的非堵塞式按键程序:


       
        ***it K1 = P1^0;
        ***it K1 = P1^1;
        ***it K1 = P1^2;
        ***it K1 = P1^3;
       
        #define KEY_VALUE_NULL        0X00
        #define KEY_VALUE_1                0X01
        #define KEY_VALUE_1                0X02
        #define KEY_VALUE_1                0X04
        #define KEY_VALUE_1                0X08
       
        unsigned char keyValue   = 0;//按键键值接口
        unsigned char keyScan1ms = 0;//按键时基驱动接口
       
        //读取按键IO口电平
        unsigned char KeyScan(void)
        {
                unsigned char temp = KEY_VALUE_NULL;
                if(K1 == 0){
                        temp = KEY_VALUE_1;
                }
                if(K2 == 0){
                        temp = KEY_VALUE_2;
                }
                if(K3 == 0){
                        temp = KEY_VALUE_3;
                }
                if(K4 == 0){
                        temp = KEY_VALUE_4;
                }
                return temp;
        }
       
        void keyProcess(void)
        {
                static unsigned        char keyLastValue = KEY_VALUE_NULL;//上次键值
                static unsigned char keyNowValue  = KEY_VALUE_NULL;//当前键值
                static unsigned char keyFilterCnt = 0;//消抖计数器
                //时基法编程核心语句
                if(keyScan1ms < 10)return;//按键扫描时基未到10ms,则退出
                keyScan1ms = 0;//千万不能忘记清零时基
               
                keyNowValue = KeyScan();//读取此时IO口电平
                if(keyNowValue != KEY_VALUE_NULL){//按键被按下
                        if(keyNowValue != keyLastValue){//此次按键跟上次按键键值不一样
                                keyFilterCnt = 0;
                        }
                        keyFilterCnt++;//消抖核心语句
                }
                else{//按键松开
                        //10ms采样一次,松手之前连续3次以上采样到按键按下。
                        if(keyFilterCnt > 3){
                                keyValue = keyLastValue;
                        }
                        keyFilterCnt = 0;//清消抖计数器
                }
                keyLastValue = keyNowValue;
        }


        void main(void)
        {
                //定时器初始化....
                while(1)
                {
                        keyProcess();
                        if(keyValue == KEY_VALUE_1){
                                keyValue = 0;//使用后手动清键值
                                //按键1被按下执行代码
                        }
                        //......
                        //其它进程...
                }
        }
        //定时器中断1ms
        void Timer0_Interrupt() interrupt 1
        {
            keyScan1ms ++;
        }




上面代码是一个最基本的非堵塞式按键,仅仅实现按键消抖,但其有非常好的扩展性,诸如组合按键、长按、单双击都可以按照这种方式实现。在此不做细述,留待读者深入体会。


非堵塞式编程的优点是非常显然的,比如将前面文章的流水灯+蜂鸣器鸣叫+LED闪烁等等进程添加进来,程序不会有任何卡顿现象出现。但如果用堵塞式编程,则程序会出现明显的卡顿现象。


但是堵塞式也并不是无可取之处,因其逻辑简单、稳定,它在处理实时性要求不高的场合非常适用。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分