单片机定时器中断实现按键去抖动问题?

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;
}
}
仔细看好问题,用定时中断实现按键去抖动,用硬件解决的就算了。

因为key_statue原来等于0,,按键刚按下时,进入外部中断,不满足条件,LED不会改变,当再次按下,定时器使按键标识置1,灯变化,注意程序时序问题。
温馨提示:内容为网友见解,仅供参考
第1个回答  2011-12-16
有四年经验的高手,小弟不惨和哦,哈哈
第2个回答  推荐于2017-11-24
if(key_statue==1)
{
key_statue=0;
led=~led;
}

你把这段代码写到主循环中,不能放到外中断中,这样就正常了,另外,把定时器的中断改成我给你的样子,要是不正常你找我!

void t0() interrupt 1 //1ms 用于按键去抖动。
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;

if(key == 0)
{
   key_num++;
  if(key_num>=15)
  {
   key_num = 15;
   key_statue=1;
  }
}
else
    {
       key_num = 0;
    }

}追问

我现在就是因为外部中断控制LED灯有问题所以加个去抖程序,还有你改的更本没去抖功能好么

追答

void t0() interrupt 1 //1ms 用于按键去抖动。
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;

if(key == 0)
{
   key_num++;
  if(key_num>=15)
  {
   key_num = 15;
   key_statue=1;
  }
}
else
    {
       key_num = 0;
key_statue=0;//-----加上这个
    }

}

//-----把下面这个写到主循环中,没必要写到外中断中,增加一个全局变量Old_Key_Status
if(key_statue != Old_Key_Status)
{
Old_Key_Status = key_statue;
if( key_statue == 1) led=~led;
}
我做了四年单片机了,刚才确实犯了个小错误

追问

大哥你这个程序和上面那个好像没什么差别啊,而且不是我需求的答案,不过还是谢谢你的解答。我一般也很少用按键来触发中断实现功能,只是今天用外部中断做试验的时候突然发现了这么个问题,所以想自己试验下外部中断中如何去抖动。过个一天如果没答案的话,分就给您了,再次谢谢您的解答。

追答

哦,是这样的啊,那我可以负责任的告诉你,如果用外中断触发按键的话,软件延时有两种写法,一是用for(;;),另一种是用定时器,不过这个时候要求外中断是低电平中断,而不能是边沿中断,为什么,你想想就明白了,而且要求定时器中断优先级要高于外中断,这样才能去抖动,但是这本质上和用for循环延时是一样的,一样的浪费了CPU,因为一直处于中断(低电平)状态,刚跳出,又中断了。
另外就只能硬件延时。
所以说,如果你听说谁用外中断做按键,还软件延时,就知道他还没有入门。

本回答被提问者采纳

单片机定时器中断实现按键去抖动问题?
因为key_statue原来等于0,,按键刚按下时,进入外部中断,不满足条件,LED不会改变,当再次按下,定时器使按键标识置1,灯变化,注意程序时序问题。

单片机定时中断实现按键扫描消抖程序,有何利弊?
中断会终止当前主程序运行,中断执行完成后主程序继续执行,总中断可能会打乱主程序时序。

51单片机,用按键实现外部中断,软件如何去抖?
外部中断的一般都是采用延时程序,而且延时程序一般是利用定时器做10~15ms的延时去抖,来实现的,而且时间不是特别精确,单片机书上和有关资料上应该都有我写一个参考一下:void DelayMS(unsigned char a){int i;for(;a>0;a--)for(i=110;i>0;i--);}延时约为a毫秒,不过不够准确,可以通过...

51单片机按键消抖方法介绍
1,任意引脚接按键,2,开个定时器中断几毫秒-几十毫秒中断一次,执行下面的函数。unsigned char Cnt=0;\/\/键按下时间计数器 if(!Key)\/\/如果键按下,{ if(Cnt)\/\/如果已经计数一次中断时间 { Cnt=0;\/\/清计数器 Key_flag =1;\/\/键识别成功 } else\/\/按键初次按下,{ Cnt++;\/\/计数器加1 }...

单片机按键编程去抖动!
根据去除抖动的时长来编程.举个例子,比如200毫秒以内的算抖动,去除,超过200毫秒认为有效.在程序中设置一个寄存器,程序开始时,把寄存器值初始化为0,另外在程序中设置一个定时器,比如10毫秒.10毫秒定时到了,可以调用一个判断按键是否按下得子程序.如果没有采集到按键按下去信号,就返回主程序;如果采集到...

为什么单片机定时器中断按键没反应
单片机定时器中断按键没有反应可能有以下原因:1. 中断优先级设置错误:在单片机中,不同的中断源有不同的优先级,如果定时器中断的优先级设置比按键中断的优先级高,那么当定时器中断正在处理时,按键中断就无法触发。解决方法是调整中断优先级,确保按键中断的优先级高于定时器中断。2. 中断屏蔽位未被...

单片机按键计数防抖的问题
1、防抖不想使用延时程序,就使用单片机内部的计时器,做内部中断;2、按键可以采用单片机的外部中断,如果按键个数比较多的话就需要外扩硬件;3、更复杂的系统可以考虑主芯片的换型。

单片机外中断消抖的问题 我的方法为什么不行?
在做按键检测时,建议设置一个10ms的定时器中断作为时钟节拍,并在中断中设置标志。程序的主循环中检测时钟节拍标志,检测到标志后清除标志并扫描按键,记录当前按键状态并和上次检测的结果做比较,并记录相同的次数,连续三次检测到同一个按键按下,则确认按键按下。这样既可以消抖保证按键的准确,又较少...

单片机菜鸟求教,关于延迟和按键去抖的问题
解决办法就是采用定时器中断。不管是按键用中断也好,显示用中断也好,只要其中一个进入定时器中断,问题就解决了。程序就不写了,描述一下意思就好 你的主程序保留键盘部分,但是显示那一大段不要了 中断本来是50ms,建议改成20ms 然后呢,设置一个变量,每次进入中断就把变量的值加1 加完以后,根据...

51单片机定时器中断问题
定时器是一直在执行的,不论是否中断,它是对节拍的计数,由单独硬件实现。单片机在中断程序中,如果中断程序比较长,定时器的计数值是会改变的,一般是先读高位计数值,再读低位计数值,然后再读一次高位计数值,防止在读的过程中,低位向高位进位。

相似回答