标题:
单片机按键延时开关灯问题求助
[打印本页]
作者:
lids
时间:
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就开始计时
}
作者:
大黄蜂001
时间:
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就开始计时
}
程序写的不完善 ,不过我觉着按照找个思路,应该可以达到你的要求
作者:
yzwzfyz
时间:
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,准备下次采样。
作者:
wulin
时间:
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
}
}
}
作者:
lids
时间:
2017-7-21 15:17
wulin 发表于 2017-7-21 09:43
修改后完美解决你的问题,有详细注释
#include
#define uchar unsigned char
谢谢,测试了一下,实现了所要的效果
作者:
lids
时间:
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; //关闭定时器
}
}
作者:
437565226
时间:
2022-5-17 15:23
大神 我想实现按键按下1分钟后灯亮 一直按着一直亮,松开后延时2分钟后灯灭,延时段内再次按下不起作用。如何实现。我改了一下咋不合适
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1