zhaolei2612 发表于 2012-4-27 20:17:12

很好的按键处理程序,无须延时来防抖动,与大家分享。

4个按键分别连接到PD的低4位。该程序实现计数器自然去抖动和实现等待按键抬起功能,而非采用延时等待的方法,同时实现了联机处理,下面程序的编译环境为avrstdio+winavr,atmeg16.
#include<avr/io.h>
unsigned char key_value;
unsigned char read_key(void)
{        static unsigned char last_key=0xff;        //初次调用认为上一次没有按键按下
        static unsigned int key_count=0;                //每检测到按键按下,则该计数器加1
        #define c_wobble_time 120   //去按键抖动时间
        #define c_keyover_time 20000//等待进入连击的时间
        #define c_keyquick_time 2000//等待按键抬起的连击时间
        static unsigned int keyover_time=c_keyover_time;
        unsigned char nc;
        nc=PIND&0x0f;            //读按键,PD0~PD3
        if(nc==0x0f)
        {        key_count=0;
                keyover_time=c_keyover_time;
                return 0xff;                        //无按键按下返回0XFF
        }
        else
        {        if(nc==last_key)               
                {        if(++key_count==c_wobble_time)return nc;                //去抖动结束,返回按键值
                        else
                        {        if(key_count>keyover_time)                //进入连击模式
                                        {        key_count=0;
                                                keyover_time=c_keyquick_time;
                                        }
                                return 0xff;
                        }
                }
                else
                {        last_key=nc;
                        key_count=0;
                        keyover_time=c_keyover_time;
                        return 0xff;
                }
        }
}
Int main(void)
{
        //….
         while(1)
      {
               key_value=read_key();
               if(key_value==......
         }
}

zhaolei2612 发表于 2012-4-27 20:19:40

希望大家能够发表自己的意见。

dragon_hn 发表于 2012-4-27 21:32:32

这样单片机忙的时候会有问题.
比较好一点的方法是开个定时器,例如1ms中断一次,在中断中设一个标识.
在主循环中看到ms中断标志就处理按键,没看到ms中断标志就不处理按键.

wxfje 发表于 2012-4-27 21:59:14

dragon_hn 发表于 2012-4-27 21:32 static/image/common/back.gif
这样单片机忙的时候会有问题.
比较好一点的方法是开个定时器,例如1ms中断一次,在中断中设一个标识.
在主循 ...

同意,我觉得这样是挺好的了

ppdd 发表于 2012-5-1 23:39:14

同意楼上的看法

Kidult 发表于 2012-5-2 19:41:43

同意中断延时的方法,这样准确,但是,如果用软件演示的方法,怎么算延时了多少?比如用很多for循环来实现延时的话,怎么知道执行力多少次for循环之后代表延时了1ms呢......我不知道单片机的指令周期是多少.....

Kidult 发表于 2012-5-2 19:42:33

其实,如果要求不是很精确的话,用软件延时很方便,个人以为

823032003 发表于 2012-5-2 19:52:23

Kidult 发表于 2012-5-2 19:41 static/image/common/back.gif
同意中断延时的方法,这样准确,但是,如果用软件演示的方法,怎么算延时了多少?比如用很多for循环来实现 ...

输出高低电平 使用示波器看一下

Kidult 发表于 2012-5-2 20:11:06

823032003 发表于 2012-5-2 19:52 static/image/common/back.gif
输出高低电平 使用示波器看一下

好方法,现在就试试~

Kidult 发表于 2012-5-2 20:13:26

823032003 发表于 2012-5-2 19:52 static/image/common/back.gif
输出高低电平 使用示波器看一下

如果我的系统时钟是8M,你看这个for执行完了之后延时是多少?
是1140×250ns=0.285ms吗?
for (i=0;i<1140;i++);
我现在用示波器测测~

geliang2008 发表于 2013-10-31 17:22:06

还是在定时器中扫描按键吧

congcong40 发表于 2014-6-2 19:58:17

dragon_hn 发表于 2012-4-27 21:32
这样单片机忙的时候会有问题.
比较好一点的方法是开个定时器,例如1ms中断一次,在中断中设一个标识.
在主循 ...

时间片的思想
页: [1]
查看完整版本: 很好的按键处理程序,无须延时来防抖动,与大家分享。