51单片机定时器中断实现按键消抖(无需延时)

单片机入门学习记录(二)

在机械按键的触点闭合和断开时,都会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理。按键的抖动对于人类来说是感觉不到的,但对单片机来说,则是完全可以感应到的,而且还是一个很“漫长”的过程,因为单片机处理的速度在“微秒”级,而按键抖动的时间至少在“毫秒”级。单片机如果在触点抖动期间检测按键的通断状态,则可能导致判断出错,即按键一次按下或释放被错误地认为是多次操作,从而引起误处理。因此,为了确保单片机对一次按键动作只作一次响应,就必须考虑如何消除按键抖动的影响。———————————————————————————(来自百度百科)

为了实现按键消抖通常有软件消抖和硬件消抖的方法。

软件消抖有采用delay()的延迟消抖,虽然代码简单,但是在函数执行时CPU无法执行其他指令,直到函数执行完毕,影响程序运行。

定时器消抖则是采用定时器中断的方法,把按键扫描程序放置在定时器中断中,可以使得扫描程序减少对于cpu的占用,但是会占用一个定时器,虽然不及硬件消抖但是对于软件消抖来说已是很高效的方法。因此采用的此方法。


通过定时器中断以5ms的速度扫描一次当前的按键值,中断程序时间设置如下,

void int_time0() interrupt 1
{
    TH0=(65536-5000)/256;
    TL0=(65536-5000)%256;
    i++;
    if(i>3)
        i=0;
    key();
}

key_flag 为按键是否按下的标志位,其初始化为0。当key按下为0,high开始加一,只有按键值被定时器扫描到2次即持续为10ms以上时,判定key0按键确实按下了,key_flag置为1。开始松手检测,检测key0为1的时间达到10ms以上时,判定key0按键是完全松开,到此为一次完整的按键动作。所以P2的状态值改变。(下面程序为单按钮示例,多个按钮可以通过放置多个标志位来实现相同效果)

void key()
{
    if(key0==0&&key_flag==0)    //按键按下
    {
        high++;
        if(high>1)        //按下消抖
        {
            high=0;
            key_flag=1;
        }
    }
    else if(key0==1&&key_flag==1)    //松手检测
    {
        low++;
        if(low>1)        //松手消抖
        {
           P2=~P2;        //状态反转
            key_flag=0;
        }
    }
}

多按钮示例如下

    if(key0==0&&key_flag1==0)    //按键按下
    {
        high1++;
        if(high1>1)        //按下消抖
        {
            high1=0;
            key_flag1=1;
        }
    }
    else if(key0==1&&key_flag1==1)    //松手检测
    {
        low1++;
        if(low1>1)        //松手消抖
        {
            key_state1=~key_state1;
            key_flag1=0;
        }
    }
    if(key1==0&&key_flag2==0)        //按键按下
    {
        high2++;
        if(high2>1)        //按下消抖
        {
            high2=0;
            key_flag2=1;
        }
    }
    else if(key1==1&&key_flag2==1)        //松手检测
    {
        low2++;
        if(low2>1)        //松手消抖
        {
            key_state2=~key_state2;
            key_flag2=0;
        }
    }
物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机定时器中断实现按键消抖(无需延时)

发表评论