打印
[51单片机]

51单片机用定时器来延时消抖怎么写

[复制链接]
3209|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
caixiaojung|  楼主 | 2014-5-14 00:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 caixiaojung 于 2014-5-14 00:56 编辑

#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar num;
sbit led1=P3^0;
sbit key=P3^4;
void main()
{
        TMOD=0x01;
        EA=1;
        ET0=1;
        TR0=1;
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
    while(1)
    {
                if(key==0)
                {
                        延时消抖//      这里怎么加上用定时器来延时消抖呢?????????????求高手指教,非常感谢
                        if(key==0)
                        {
                                led=0;
                        }
                }
    }
}
void T0_time() interrupt 0
{
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        num++;        
}

相关帖子

沙发
思宁| | 2014-5-14 08:25 | 只看该作者
本帖最后由 思宁 于 2014-5-14 08:37 编辑

这程序,首先中断号写错!其次,你声明sbit led1=P3^0;而你下面程序却用led.还有最好加个检测释放按键的动作。你想实现的效果是按键按一次LED灯灭,在按一次按键LED灯亮吗?如果是的话
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char

uchar num;
sbit led1=P3^0;
sbit key=P3^4;
void main()
{
        TMOD=0x01;
        EA=1;
        ET0=1;
        //TR0=1;
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        while(1)
        {
                if(key==0)
                {
                        TR0 = 1;
                        while(num<=1);
                        TR0 = 0;
                        num = 0;               
                        if(key==0)
                        {
                                while(!key);
                                led1 = ~led1;
                        }       
                }
        }
}
void T0_time() interrupt 1
{
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        num++;        
}







使用特权

评论回复
板凳
思宁| | 2014-5-14 08:30 | 只看该作者
另外按键检测,推荐看看状态机

使用特权

评论回复
地板
ningling_21| | 2014-5-14 08:43 | 只看该作者
发现按键按下后,启动20毫秒计时,20毫秒内不用检测也可以检测,20毫秒后检测按键是否依然没有释放...

使用特权

评论回复
5
airwill| | 2014-5-14 12:01 | 只看该作者
支持一下新人.
常用的办法是 定时器做成定时时钟, 比如 5mS. 定时到后检测键盘, 有信号就加一, 无信号减到0 为止, 若这个累计数超过某个值, 比如 3, 就算按键消抖为有, 0 就算消抖为无.

使用特权

评论回复
6
限量_个性。| | 2014-5-14 13:13 | 只看该作者
按键状态机的方式挺好用。定时器中断里设置标志位(如10ms),主函数可通过检测标志位扫描按键,将按键的检测过程分成几个不同的状态,初始状态-按键按下确认状态-按键释放状态,还可以实现长按,短按的功能,功能越多,状态就越多。LZ可以查阅相关资料,先自己尝试下。

使用特权

评论回复
7
限量_个性。| | 2014-5-14 13:15 | 只看该作者
这样不仅能实现消抖,松手检测都省了。。

使用特权

评论回复
8
caixiaojung|  楼主 | 2014-5-16 19:16 | 只看该作者
本帖最后由 caixiaojung 于 2014-5-16 19:18 编辑

/*这个程序是按键短按一次led1,led2亮,再按一次都灭,
长按一秒lde1,lde2,lde3都亮,再按一次全灭,现在有个
问题是如果不停的短按有时会三个lde灯都亮,也不是每
次都会错,没规律的偶尔错一次,不知道什么问题,忘大
家指点一二*/
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit led1=P1^0;
sbit led2=P1^1;
sbit led3=P1^2;
sbit key=P3^7;
void delay(uint);
uchar ds0,ds1,num1,num2;
void keyscan();
void main()
{
    TMOD=0x11;
    EA=1;
    ET0=1;
        ET1=1;
    TH0=0x3C;
    TL0=0xB0;
        TH1=0x8A;
        TL1=0xD0;
        ds0=0;
        ds1=0;
        key=1;
    while(1)
    {
        keyscan();
    }
}
void keyscan()
{
        ds0=0;
    key=1;
    if(num1==1||num2==1)//判断只要按键按下去过一次记数,再按就三个LED灯全灭.
    {        
        if(!key)
        {
                        TR1=1;
                        while(ds1<=1);//消抖
                        TR1=0;
                        ds1=0;
            if(!key)
            {
                while(!key);
                num1=0;
                num2=0;
                led1=1;
                led2=1;
                led3=1;
            }
        }
    }
else
    {
        if(!key)
        {
                        TR1=1;
                        while(ds1<=1);//消抖
                        TR1=0;
                        ds1=0;
            if(!key)
            {
                                TR0=1;
                while(!key && ds0<=15);//判断长按3个LED全亮
                                TR0=0;
                                ds0=0;
                        if(!key)
                        {
                num2=1;
                led1=0;
                led2=0;
                                led3=0;
                while(!key); //松手
                        }      
                else//否则就是短按两个LED灯亮
                {
                        num1=1;
                        led1=0;
                        led2=0;
                }                                               
            }
        }
    }
}
void T0_time()interrupt 1//长按定时器0
{
        TH0=0x3C;
        TL0=0xB0;
        ds0++;
}
void T1_time()interrupt 3//消抖定时器1
{
        TH1=0x8A;
        TL1=0xD0;
        ds1++;
}

使用特权

评论回复
9
电子无聊大神| | 2014-5-16 19:38 | 只看该作者
5L、6L都是不错的方法。

使用特权

评论回复
10
lmc123ms| | 2014-6-20 16:59 | 只看该作者
不错的想法。

使用特权

评论回复
11
coody| | 2014-6-20 18:21 | 只看该作者
我都是用定时器产生一些时隙,把程序按运行的频度放在时隙中运行。
比如按键,隔32ms调用一次。

使用特权

评论回复
12
rtgchym| | 2014-6-25 10:17 | 只看该作者
为什么不考虑从硬件上消抖呢

使用特权

评论回复
13
ayb_ice| | 2014-6-25 15:51 | 只看该作者
本帖最后由 ayb_ice 于 2014-6-25 15:52 编辑




#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char

uchar num;
uchar delay;
sbit led1=P3^0;
sbit key=P3^4;

void main()
{
        TMOD=0x01;
        EA=1;
        ET0=1;
        TR0=1;
        TH0=(65536-10000)/256;
        TL0=(65536-10000)%256;
        while(1)
        {
                if(key==0)
                {
                        延时消抖//      这里怎么加上用定时器来延时消抖呢?????????????求高手指教,非常感谢

                        key_delay(2);
                        if(key==0)
                        {
                                led=0;
                        }
                }
        }
}

void T0_time(void) interrupt 1
{
        TH0=(65536-10000)/256;
        TL0=(65536-10000)%256;
        num++;
        if(delay) delay--;
}


void key_delay(uchar d)
{
        delay = d;

        while(delay){
                PCON |= 0x01;
        }

}





使用特权

评论回复
14
coody| | 2014-6-25 18:13 | 只看该作者
rtgchym 发表于 2014-6-25 10:17
为什么不考虑从硬件上消抖呢

因为成本。

使用特权

评论回复
15
rtgchym| | 2014-6-25 19:55 | 只看该作者
coody 发表于 2014-6-25 18:13
因为成本。

这都行,那能增加个什么成本

使用特权

评论回复
16
rtgchym| | 2014-6-25 19:56 | 只看该作者
如果真差那点成本的话就用状态机,按时间片扫

使用特权

评论回复
17
18273602045| | 2016-4-9 16:31 | 只看该作者
思宁 发表于 2014-5-14 08:25
这程序,首先中断号写错!其次,你声明sbit led1=P3^0;而你下面程序却用led.还有最好加个检测释放按键的动 ...

请问大神,代码中while(num<=0)什么意思,急求,谢谢

使用特权

评论回复
18
18273602045| | 2016-4-10 10:01 | 只看该作者
那请问思宁写的程序中 while(num<=1);是什么意思

使用特权

评论回复
19
ywlzh| | 2016-4-10 11:33 | 只看该作者
哎 既然用了定时器 就不要在主函数里去扫描按键了

先考虑一个问题,1s你能按按键多少次?这个问题要是想的明白,那就简单了

简单粗暴的解决方法就是你定100ms的时间,中断里去做扫描按键,有按键按下了,直接做或者发状态告诉主程序,延时消抖,不用做了!

这样你可否明白?

不信?你可以编一下程序。

这个方法还可以改进,那就是用两个变量可以判断长按和短按.........

unsigned char Trg;
unsigned char Cont;
void KeyRead( void )
{
    unsigned char ReadData = PINB^0xff;   // 1
    Trg = ReadData & (ReadData ^ Cont);      // 2
    Cont = ReadData;                                // 3
}
自行思考!

使用特权

评论回复
20
洛理小子| | 2016-4-10 19:04 | 只看该作者
跟着学习新方法了~~~

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

5

帖子

0

粉丝