找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5527|回复: 6
打印 上一主题 下一主题
收起左侧

单片机按键延时开关灯问题求助

[复制链接]
跳转到指定楼层
楼主
ID:140489 发表于 2017-7-20 16:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//这单片机程序实现的功能是: 按键按下,延时1秒灯亮,如果按键按住不放,灯就一直亮,松手后,延时30秒灯熄灭;
//上面描述的功能实现了,我想加一个功能,如果在灯没有熄灭的情况下,再次按下按键,延时熄灭的时间在上次延时时间上累加,
//想了好久,没能实现第二个功能,请大神们看下,该怎么写呢
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

bit a;//计时标志

uint num;//计时变量

sbit LED1 = P1^0;

sbit K1 = P3^0;

void delay(uint x)
{
  uint i,j;
  for(i=x;i>0;i--)
          for(j=120;j>0;j--);
}
void main(void)
{                                                                            //模拟点动延时开关灯
     EA = 1;
     ET0 = 1;
     TMOD = 0x01;
     TH0 =(65536-50000)/256;//定时50ms应该要50000
     TL0 =(65536-50000)%256;
         TR0=1;
        while(1)
            {
              if(K1==0)
                {
                  delay(1000);
                          if(K1==0)
                                  {
                             LED1=0;         //LED1亮,一直按住K1, LED1就一直亮。测试通过
                                         while(!K1);         //松手后
                                         a=1;


                                   }
                  }
        
                if(num==600)//num 50毫秒加1,延时30秒 即30000/50=600次
                {
                                num = 0;// 计时值必须清零,否则第2次按开关,灯会长亮
                        a = 0;    //清除标志
                        LED1 = 1; //灯熄灭        
                }

             }   
}


void time0() interrupt 1
{
     TH0 =(65536-50000)/256;
     TL0 =(65536-50000)%256;
        if(a==1)num++;  //判断计时标志是否为1,为1就开始计时
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:211467 发表于 2017-7-20 23:03 | 只看该作者
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
bit a;//计时标志
uint num;//计时变量uchar num2;//在次按下次数标志
sbit LED1 = P1^0;
sbit K1 = P3^0;

void delay(uint x)
{
  uint i,j;
  for(i=x;i>0;i--)
          for(j=120;j>0;j--);
}

void main(void)
{                                                                            //模拟点动延时开关灯
     EA = 1;
     ET0 = 1;
     TMOD = 0x01;
     TH0 =(65536-50000)/256;//定时50ms应该要50000
     TL0 =(65536-50000)%256;
     TR0=1;
     while(1)
      {
         if(K1==0)
         {
            delay(1000);
             if(K1==0)
                {
                LED1=0;         //LED1亮,一直按住K1, LED1就一直亮。测试通过
                while(!K1);         //松手后
                a=1;
                 }
                 if(K1==0)
                  {
                 delay(1000);
                    if(K1==0)
                       num2++;
                  }
       }
      if(num==(600*num2))    //num 50毫秒加1,延时30秒 即30000/50=600次
          {
          num = 0;// 计时值必须清零,否则第2次按开关,灯会长亮
          a = 0;    //清除标志
          LED1 = 1; //灯熄灭        
        }
     }   
}

void time0() interrupt 1
{
     TH0 =(65536-50000)/256;
     TL0 =(65536-50000)%256;
        if(a==1)num++;  //判断计时标志是否为1,为1就开始计时
}




程序写的不完善 ,不过我觉着按照找个思路,应该可以达到你的要求
回复

使用道具 举报

板凳
ID:123289 发表于 2017-7-21 00:14 | 只看该作者
1、做两个键标记,K_LAST、K_THIS,一个记上次键值,一个记本次键值。按下为1。
   这样就能知道按下、弹起、按住不放了。提示:所谓上次、本次都应经防弹动过滤(自己去做防弹动)。
2、做一个1S计时器:R_1S,一个起动标记B_1S。
   T0中断后:如果B_1S=1,就将R_1S+1,当R_1S=1秒时:就清B_1S=0,不再计时,并亮灯。
   主程序中:当键“按下”(K_LAST=0、K_THIS=1)时:置B_1S=1。
3、做一个30S计时器:R_30S,一个起动标记B_30S。
   T0中断后:如果B_30S=1,就将R_30S-1,当R_30S=0秒时:就清B_30S=0,不再计时,并灭灯。
   主程序中:当按键弹起时(K_LAST=1、K_THIS=0),置B_30S=1,R_30S=R_30S+30秒(提示:应防溢出)。
就这么简单!
提示:扫键时,将读到的健值放入K_THIS,然后做键处理、判定,结束后将K_LAST=K_THIS,准备下次采样。
回复

使用道具 举报

地板
ID:213173 发表于 2017-7-21 09:43 | 只看该作者
修改后完美解决你的问题,有详细注释
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
bit sign_a=0,sign_b=0,sign_c=0,sign_d=0;//标志
uint count1=0,count2=0;                                        //计数器
sbit LED1 = P1^0;
sbit key = P3^0;

void keyscan()                                        //按键扫描程序
{
        static uchar count=0;                //消抖计数变量                       
        if(key==0)                                        //检测按键如果为0
        {
                count++;                                //消抖计数
                if(count>=100)                        //重复检测按键如果为0
                {                       
                        count=100;                        //防止溢出
                        if(sign_c==0)                //按键自锁标志为0
                        {
                                sign_a=1;                //延时1秒启动标志
                                sign_c=1;                //按键自锁标志置1,防止一次按键多次响应
                                EA = 0;                        //关闭总中断,防止改变count2时与中断冲突
                                count2+=600;        //每30秒延时累加(600),最大累加到54.5分钟,超过109次溢出
                                EA = 1;                        //开启总中断
                        }
                }
        }
        else                                                //按键抬起
        {
                if(sign_c==1)                        //如果按键自锁标志为1
                {
                        sign_c=0;                        //按键自锁标志清0
                        sign_d=1;                        //按键按下后再抬起标志为1
                }
                count=0;                                //消抖计数清0
        }
}

void main(void) //@12T、12MHz、定时50ms
{
        TMOD = 0x01;
        TH0 =(65536-50000)/256;                //设置定时初值
        TL0 =(65536-50000)%256;                //设置定时初值
        TR0=1;
        EA = 1;
        ET0 = 1;
        while(1)
        {
                keyscan();                                //按键扫描
/*******显示部分********/
                if(sign_b==1)                        //1秒延时结束
                        LED1 = 0;                        //LED1亮
                else
                        LED1 = 1;                        //LED1灭
        }   
}

void time0() interrupt 1
{
        TH0 =(65536-50000)/256;                //设置定时重载值
        TL0 =(65536-50000)%256;                //设置定时重载值
        if(sign_a==1)                                  //判断计时标志,启动延时1秒
        {
                count1++;                                //计数器1自+1
                if(count1>=20)                        //1秒延时到
                {
                        count1=0;                        //计数1清0
                        sign_a=0;                        //1秒延时标志清0
                        sign_b=1;                        //30秒延时标志
                }
        }
        if((sign_b==1)&(sign_d==1)) //30秒延时标志与按键抬起标志
        {
                count2--;                                //计数器2自-1
                if(count2==0)                        //N+30秒延时到
                {
                        sign_b=0;                        //30秒延时标志清0
                        sign_d=0;                        //按键抬起标志清0
                }
        }
}

回复

使用道具 举报

5#
ID:140489 发表于 2017-7-21 15:17 | 只看该作者
wulin 发表于 2017-7-21 09:43
修改后完美解决你的问题,有详细注释
#include  
#define uchar unsigned char

谢谢,测试了一下,实现了所要的效果
回复

使用道具 举报

6#
ID:140489 发表于 2017-7-21 16:36 | 只看该作者
刚才又写了一个小程序
//功能:按键按下,延时1秒灯亮,如果按键按住不放,灯一直亮,松手后延时30秒灯熄灭;
//      如果在灯没熄灭的时候,再次按下按键不放,灯一直亮,松手后延时30秒灯熄灭。
//模拟点动延时开关灯,测试通过
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

uchar R_1S;                  //1秒计时变量
uint R_30S=600;                 //30秒计时变量
bit B_1S;                         //1秒计时标志
bit B_30S;                         //30秒计时标志

sbit LED1 = P1^0;   //定义LED灯端口
sbit K1 = P3^0;            //定义按键端口


void main(void)
{                                                                           
     EA = 1;
     ET0 = 1;
     TMOD = 0x01;
     TH0 =(65536-50000)/256;//定时50ms应该要50000
     TL0 =(65536-50000)%256;
//         TR0=1;
        while(1)
            {
              if(K1==0)                           //按键按下
                {
                          TR0=1;                          //启动定时器
                  B_1S=1;                          //1秒计时标志置1
                          if(R_1S==20)          //如果1秒计时变量为20,说明1秒时间到
                                {
                                        if(K1==0)          //如果按键还在按下状态
                                          {          
                                                 TR0=0;          //关闭定时器
                                     R_1S=0;  //1秒计时变量清零
                                                 LED1=0;       //LED1亮,一直按住K1, LED1就一直亮。
                                                 while(!K1);   //松手后
                                                 TR0=1;                   // 启动定时器
                                                 B_1S=0;           //1秒计时标志清零
                                                 B_30S=1;           //30秒计时标志置1
                                        }
                                }
                  }

                          if(R_30S>0 && R_30S<600 )        //如果30秒计时变量大于0,并小于600,这时灯是亮的,再延时熄灭的过程
                          {
                                  if(K1==0)                                //这时如果按键按下
                                {
                                        B_1S=1;                                //1秒计时标志置1
                                        if(R_1S==20)                //如果1秒计时变量为20,说明1秒时间到
                                        {
                                                if(K1==0)                //如果按键还在按下状态
                                                {       
                                                        TR0=0;                //关闭定时器
                                                        R_30S=1;        //30秒计时变量清1
                                                        LED1=0;                // LED1就一直亮
                                                        R_1S=0;                //1秒计时变量清零
                                                        B_30S=0;        //30秒计时标志清零
                                                        while(!K1);        //松手后
                                                        TR0=1;                   // 启动定时器
                                                        B_1S=0;                   //1秒计时标志清零
                                                        B_30S=1;           //30秒计时标志置1
                                                        R_30S=R_30S+599; //30秒计时变量位1+599=600,计时自减用       
                                                }       
                                        }       
                                }
                          }
                       
             }   
}


void time0() interrupt 1
{
    TH0 =(65536-50000)/256;          //重装初值
    TL0 =(65536-50000)%256;          //重装初值
       
        if(B_1S==1)           //如果1秒计时标志为1
        R_1S++;                   //1秒计时变量自加1
       
        if(B_30S==1)   //如果30秒计时标志为1
        R_30S--;           //30秒计时变量自减1
               
        if(R_30S==0)   //30秒计时变量为0
        {
                R_30S=600; //30秒计时变量赋值600,以备下次自减
                LED1=1;           //熄灭LED灯
                B_30S=0;   //30秒计时标志清零
                TR0=0;           //关闭定时器
        }

}
回复

使用道具 举报

7#
ID:858627 发表于 2022-5-17 15:23 | 只看该作者
大神 我想实现按键按下1分钟后灯亮 一直按着一直亮,松开后延时2分钟后灯灭,延时段内再次按下不起作用。如何实现。我改了一下咋不合适
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表