在实际工程中常用到中断的算法来实现按键消抖。
思路:启动一个定时中断,每2ms进一次中断扫描按键状态并储存。连续扫描8次后,观察这8次按键状态是否一致。如果一致,即按键没有发生动作,处于稳定状态。
被监测到的按键动作,通常如下图所示:
具体代码如下:
#include <reg52.h>
unsigned char code LedChar[10]={//数码管显示的数字0~9。
0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
sbit KEY1 = P3^3;
sbit DigitalTube = P1^0;
bit KeySta = 1; //当前按键状态。
void main()
{
bit backup = 1;//按键值备份,保存前一次扫描的值。
unsigned char cnt = 0;//按键计数,记录按键按下的次数。
EA = 1;//中断总开关。
ET0 = 1;//使能中断。
TH0=0XF8;//定时器设定,定时2ms。
TL0=0XCD;
TR0 = 1;//启动T0。
KEY1 = 1; //按键引脚输出高电平。
while(1)
{
DigitalTube = 0;
P0 = LedChar[cnt];
if(backup != KeySta) //当前值不同于前一次的值。
{
if(backup == 0) //如果前值为0,说明当前状态是0->1,即按键弹起。
{
cnt++;
if(cnt>9)
{
cnt = 0;
}
}
backup = KeySta; //更新备份位当前值,以便进行下一次比较。
}
}
}
//T0中断服务函数,用于扫描按键状态
void InterruptTimer0()interrupt 1
{
static unsigned char keybuf = 0XFF; //扫描缓冲区,保存一段时间内的扫描值。
TH0=0XF8;
TL0=0XCD;
keybuf = (keybuf<<1)|KEY1; //缓冲区左移一位,并将当前扫描值移入最低位。
if(keybuf == 0X00)
{ //连续8次扫描值为0,即16ms内都只检测到按下状态,可认为按键已按下。
KeySta = 0;
}
else if(keybuf == 0XFF)
{ //连续8次扫描值为1,即16ms内都只检测到弹起状态,可认为按键已弹起。
KeySta = 1;
}
else
{} //其他情况。按键状态不确定,不更新KeySta变量值。
}