51单片机用外部中断实现按键控制时如何消抖?

以下是按下一次按键实现数码管上数字加减1的正确的代码,但在实际单片机上发现按下一次按键因为抖动可能加减多次,如果不使用查询方式仍然使用中断的方法,那该如何避免这个问题呢

#include<REG52.H>
sbit P16=P1^6;
sbit P17=P1^7;
sbit K1=P3^2;
sbit K2=P3^3;
unsigned int a,b;
void Delay(){
    unsigned int i=0;
    for(i=0;i<10;i++);
}
void init(){    //init函数直接给数码管赋初值
    a=0,b=9;
}
void display(){
    unsigned char discode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
    for(;;)
    {
        P0=discode[a];
        P16=0;
        Delay();
        P16=1;
        P0=discode[b];
        P17=0;
        Delay();
        P17=1;
    }
}
void int0_sr() interrupt 0
{
    if(K1==0)
        if(b==9)
            if(a==9) a=0,b=0;
            else b=0,a++;
        else b++;
}
void int1_sr() interrupt 2
{
    if(K2==0)
        if(b==0)
            if(a==0) a=0,b=0;
            else b=9,a--;
        else b--;
}
void main(){
    IT0=EX0=1;
    IT1=EX1=1;
    EA=1;
    init();
    display();
}

可以在中断触发后加入一段延时代码,等待抖动结束再执行处理代码,这样可以避免抖动造成的误触发。以下是修改后的代码:


#include<REG52.H>
sbit P16=P1^6;
sbit P17=P1^7;
sbit K1=P3^2;
sbit K2=P3^3;
unsigned int a,b;

void Delay(){
    unsigned int i=0;
    for(i=0;i<10;i++);
}

void init(){
    a=0,b=9;
}

void display(){
    unsigned char discode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
    for(;;){
        P0=discode[a];
        P16=0;
        Delay();
        P16=1;
        P0=discode[b];
        P17=0;
        Delay();
        P17=1;
    }
}

void int0_sr() interrupt 0
{
    if(K1==0){
        // 延时处理
        Delay();
        if(K1==0){
            // 抖动已结束,执行处理代码
            if(b==9)
                if(a==9) a=0,b=0;
                else b=0,a++;
            else b++;
        }
    }
}

void int1_sr() interrupt 2
{
    if(K2==0){
        // 延时处理
        Delay();
        if(K2==0){
            // 抖动已结束,执行处理代码
            if(b==0)
                if(a==0) a=0,b=0;
                else b=9,a--;
            else b--;
        }
    }
}

void main(){
    IT0=EX0=1;
    IT1=EX1=1;
    EA=1;
    init();
    display();
}