以Key4为例,使用定时中断2ms进行消抖,对连续8次(16ms)的按键状态进行判断.
如果全部为1则弹起,将按键当前状态(Keysta)为1;
全部为0则按下,将按键当前状态(Keysta)置0;
其余状态都为抖动,按键当前状态不变。
在主程序里对按键状态进行判断,如果按键当前状态(Keysta)与按键历史状态(backup)不同,则说明按键状态发生变化。程序中是弹起时,按键次数改变,将最新的按键次数送给数码管显示,将按键历史状态更新为当前状态并进行下一次判断。源代码如下:
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit KEY1 = P2^4;
sbit KEY2 = P2^5;
sbit KEY3 = P2^6;
sbit KEY4 = P2^7;
unsigned char code LedChar[] ={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};
bit KeySta = 1; //位定义
void main()
{
bit backup = 1; //定义一个位变量,保存前一次扫描的按键值。
unsigned char cnt = 0;
EA = 1;
ENLED = 0; //使能U3 选中数码管DS1
ADDR3 = 1;
ADDR2 = 0;
ADDR1 = 0;
ADDR0 = 0;
TMOD = 0x01; //T0为模式1
TH0 = 0xf8; //定时2ms
TL0 = 0xcd;
ET0 = 1;
TR0 = 1; //启动T0
P2 = 0xf7; //P2.3置0,即输出低电平
P0 = LedChar[cnt]; //显示按键次数
while(1)
{
if(KeySta != backup) //当前值与前次值不相等说明此时有动作
{
if(backup == 0) //如果前次值为0,则说明是弹起动作
{
cnt++; //按键次数加1
if(cnt >= 10)
{
cnt = 0; //10次清0
}
P0 = LedChar[cnt];
}
backup = KeySta; //更新备份为当前值
}
}
}
/*T0中断服务函数,用于按键状态的扫描并消抖*/
void InterruptTimer0() interrupt 1
{
static unsigned char keybuf =0xff; //扫描缓冲区,保存一段时间内的扫描值
TH0 = 0xf8; //重新加载初值
TL0 = 0xcd;
keybuf= (keybuf<<1) |KEY4; //缓冲区左移一位,并将当前扫描值移入最低位
if(keybuf == 0x00) //连续8次扫描值都为0,16ms内状态不变,即按键已按下
{
KeySta = 0;
}
else if(keybuf == 0xff) //连续8次扫描值都为1,16ms内状态不变,即按键已弹起
{
KeySta = 1;
}
else //其他情况则按键状态还未稳定
{}
}