51单片机教程:按键的定时器消抖(有延时的程序不是好程序)


按键消抖原理

一、首先来回顾一下按键延时消抖
按键由于是机械结构,按下的时候难免产生抖动,一般抖动会在按下的时候与松开的时候产生,抖动时间大概是10ms
在这里插入图片描述
于是针对按键抖动就有了延时消抖的一种简单的解决方法:

二、按键消抖代码
方法一: 按下按键损耗的时间取决于按下按键到松开的时间,至少10ms,按下按键后CPU不再执行其他指令,直到按键松开,应用能力弱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void main(void)
{
    while(1)
    {
        if(key==0)    //读P1.0引脚,如果引脚为低电平,则进入if
        {
            delay_ms(10); //延时10ms消抖
            if(key==0)   //再次判断按键是否按下,防止干扰,增强稳定
            {
                 led = !led;//led状态改变
                 while(key==0);//等待按键松开,防止往下执行
            }
        }
    }
}

方法二: 按下按键损耗的时间大约10ms,松开按键时损耗10ms,累计20ms,按下按键期间可以进行其他操作,应用能力较强

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void main(void)
{
    int status=0;   //按键标志位
    while(1)
    {
        if(status==1 && key==1)  //判断按键是否松开
        {
            delay_ms(10);  //延时消抖
            if(key==1 && status==1) //再次判断,排除是外界杂波干扰
            {
                status=0; //更改标志防止循环执行判断松开程序
            }
        }
        if(key==0 && status==0)//判断按键是否按下
        {
            delay_ms(10);//延时消抖
            if(key==0 && status==0)    //再次判断,排除是松开状态或外界杂波干扰
            {
                status=1;//防止循环执行按键控制程序
                led=!led;
            }
        }
    }
}

可以看到,延时消抖最大的弊端就是有延时,至少要消耗10ms~20ms的时间,对于我们来说10ms或许很短,但对于一些高性能的MCU来说,那就是能执行几万条指令的时间

按键定时器消抖

一、按键消抖
按键消抖一般分为4步:
1、判断按键是否按下
2、消抖
3、再次判断按键是否按下
4、等待按键松开
二、定时器消抖原理
1、判断按键是否按下,
2、若检测到有按键按下,则开启定时器,开启定时中断,定时时间为10ms 左右,使得按键按下10ms后进入定时中断,进入中断的时候按键抖动时间已过
3、在定时器中断中再次判断按键是否按下
4、关闭定时器,等待按键松开

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <reg51.h>
sbit key=P1^0;  //定义key为P1.0
sbit led=P2^0; //定义LED为P2.0

void main(void)
{
    TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
    TH0=(65536-10000)/256;  //给定时器赋初值,定时10ms
    TL0=(65536-10000)%256;
    ET0=1;//打开定时器0中断允许
    EA=1;//打开总中断
    TR0=0;//关闭定时器        
    while(1)
    {
        if(key==0)    //读P1.0引脚,如果引脚为低电平,则进入if
        {
            TR0=1;//打开定时器
        }
    }
}

/*定时器中断*/
void Timer0() interrupt 1
{
    TH0=(65536-10000)/256;  //给定时器赋初值,定时10ms
    TL0=(65536-10000)%256; 

    TR0=0;//打开定时器
    if(key==0)   //再次判断按键是否按下
    {  
        led=!led;
        while(key==0);    //等待按键松开
    }
}