51单片机定时器消抖的问题。高手进

51单片机在用外部中断0控制LED灯亮灭时,可能没去抖动吧,一运行LED灯就在闪烁,用空循环延迟去抖太浪费CPU了不好,所以我用定时器0中断编写了个较简陋的程序实现按键去抖动功能(程序逻辑可能没那么严谨)。程序的问题是:按键第一次按下后没有反应,但之后再次按下按键就正常工作了,能控制LED灯的亮灭,下面是我的程序和电路图,希望有大神可以给予指导。
#include<reg52.h>
#define uchar unsigned char
#define uchar unsigned char
uchar key_num;
bit key_statue; //按键标识
uchar ms;
sbit key=P3^2;
sbit led=P1^0;
void main(void)
{
TMOD=0x01;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
ET0=1;
EX0=1;
TR0=1;
IT0=1;
PT0=1;
EA=1;
key_statue=key_num=0;
led=1;
while(1);
}

void t0() interrupt 1 //1ms 用于按键去抖动。
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
ms++;
if(key==0)key_num++;
if(ms==15) //15秒刷新一次
{
if(key_num>10) //15秒钟如果低电平持续时间大于10秒就认为按键按下,而不是抖动
key_statue=1; //按键标识位置1
ms=0;
key_num=0;
}
}

void int0() interrupt 0 //外中断0,设定工作模式
{
if(key_statue==1)
{
key_statue=0;
led=~led;
}
}

请仔细看清楚问题,看清楚程序,可以实际运向下。
第一次不能实现功能,后面就可以了。请问这是为什么,一个怎样修改? 3Q

ms++;
if(key==0)key_num++;
if(ms==15) //15秒刷新一次
{
if(key_num>10) //15秒钟如果低电平持续时间大于10秒就认为按键按下,而不是抖动
key_statue=1; //按键标识位置1
ms=0;
key_num=0;
}
这部分有问题,改为:

if(key==0)
{
key_num++;
}
else
{
key_num=0;
}

if(key_num>10) //如果低电平持续时间大于10ms就认为按键按下,而不是抖动
{
key_statue=1; //按键标识位置1
}追问

改了一下烧进去还是和原来效果一样,第一次中断不起作用后面就正常了

追答

原来你后面用了外中断,这样是会在第一次没有反应的,其实这个程序不要外中断,就用void t0() interrupt 1就够了。

这里面的原因是因为第一次外中断进入以后key_statue=0;没有=1.

温馨提示:内容为网友见解,仅供参考
第1个回答  2014-06-26
你可以在T0中设置中断调试一下,在第一次按键时,单步运行T0中断,看一下程序是如何工作的。
我觉得T0中断处理程序有些问题,建议按使用下面的程序,int0可以不用。

bit key_D0;

bit key_D1;

void t0() interrupt 1 //定时间隔决定去抖动的间隔,可以将T0定时设置为20ms。
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256; //自己计算一下20ms的数值吧。
key_D1 = key_D0;
key_D0 = key;
if (key_D1 == key_D0){
if (key_D1 == 1){
if (key_statue==0){

led=~led; //按一次键,灯亮灭交替一次

}

key_statue=1; //按键标识位置1
}else{

key_statue=0; //按键标识位置0

}

led=key_statue; //按键时灯亮,松键时灯灭
}
}

led=~led; //按一次键,灯亮灭交替一次
led=key_statue; //按键时灯亮,松键时灯灭
这两个只能选用一个。因为不太清楚你要哪种控制方式。
相似回答