找回密码
 立即注册

QQ登录

只需一步,快速开始

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

请问怎么写这个10s灯灭的语句 帮下忙解解惑

  [复制链接]
跳转到指定楼层
楼主
按下按键灯亮 松按键灯灭
按下按键10s灯灭(一直按按键不松灯也灭)

用计时器完成10s的计时

请问怎么写这个10s灯灭的语句

关键是一直按着按键如何能让灯灭呢

写了if语句不能保证按键按着还能够灯灭
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

来自 5#
ID:213173 发表于 2018-2-9 08:29 | 只看该作者
weiwei850113 发表于 2018-2-8 21:53
困扰我好几天了

就是写不出按键按着灯灭的语句

给你一个例程,按键和LED端口根据你的实际电路定义
#include <AT89X52.H>
#define uint unsigned int
#define uchar unsigned char
sbit key=P3^4;                                        //按键端口定义       
sbit LED=P1^0;                                        //发光管端口定义
uchar Cnt50ms=0;                                //中断计数变量

void Timer0Init()                                //50毫秒@12.000MHz
{
        TMOD= 0x01;                                        //设置定时器模式
        TL0 = 0xB0;                                        //设置定时初值
        TH0 = 0x3C;                                        //设置定时初值
//        TF0 = 0;                                                //清除TF0标志
//        TR0 = 1;                                                //定时器0开始计时
        EA=1;                                                        //开总中断
        ET0=1;                                                //开定时器0中断       
}
void keyscan()                                        //按键识别子程序
{
        static bit key_sign=0;        //按键有效标志
        static uint  count=0;        //计数变量                       
        if(key==0)                                        //检测按键如果为0
        {
                count++;                                        //消抖计数
                if((count>=500)&&(key_sign==0))
                {                       
                        key_sign=1;                        //按键有效标志置1
                        Cnt50ms=0;                        //中断计数变量清0
                        TR0 = 1;                                //启动定时器
                        LED=0;                                //发光管亮
                }
        }
        else                                                        //按键抬起
        {
                key_sign=0;                                //按键有效标志清0
                count=0;                                        //消抖计数清0
                LED=1;                                        //发光管灭
                TR0=0;                                        //关闭定时器
        }
}
void main()
{
        Timer0Init();                                //定时器0初始化
        while(1)
        {
                keyscan();                                //按键扫描
        }
}
void timer0() interrupt        1        //定时器0中断
{
        TL0 = 0xB0;                                        //设置定时初值
        TH0 = 0x3C;                                        //设置定时初值
        Cnt50ms++;
        if(Cnt50ms>=200)                        //10秒
        {
                Cnt50ms=0;
                LED=1;                                        //发光管灭
                TR0=0;                                        //关闭定时器
        }
}

评分

参与人数 2黑币 +18 收起 理由
通天塔 + 8 很给力!
weiwei850113 + 10 很给力!

查看全部评分

回复

使用道具 举报

来自 8#
ID:47286 发表于 2018-2-10 22:30 | 只看该作者
随便写了下思路 供你参考吧

这个思路的问题是 不管什么时候 都有个防抖延时的损失 等于程序的实时性有点差 不过一般防抖都是15~20ms 对于你初学 不要求运行精度的情况下没什么影响 至少人去按键时感觉不出来有什么差别

严谨的话还是用标记或者进程来控制状态好 你慢慢来 将来会搞得很好的

如果 按键按下
{
        防抖延时
        如果 按键依旧按下
        {
                如果 计数器01清零标记==0
                {
                        计数器01清零
                        计数器01清零标记置位
                }
                如果 灯为灭状态
                {
                        开灯
                }
                如果 计数器01达到设定值
                {
                        如果 灯为开状态
                        {
                                关灯
                                等待按键释放
                                计数器01清零标记清零
                        }
                }
        }
}

如果 按键松开(等同于未按下)
{
        防抖延时
        如果 按键松开
        {
                如果 等为亮状态
                {
                        关灯
                }
        }
        计数器01清零标记清零
}

评分

参与人数 1黑币 +80 收起 理由
admin + 80 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

沙发
ID:241249 发表于 2018-2-8 21:53 | 只看该作者
困扰我好几天了

就是写不出按键按着灯灭的语句
回复

使用道具 举报

板凳
ID:155507 发表于 2018-2-8 23:17 | 只看该作者
用同一个按键 利用外部双向中断(上升沿+下降沿)处理。
回复

使用道具 举报

地板
ID:280994 发表于 2018-2-8 23:44 | 只看该作者
按键触发检测的方式改为边沿检测,这样按住的话没有边沿信号不久可以了嘛

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

6#
ID:126165 发表于 2018-2-9 09:59 | 只看该作者
按键触发的是计时器的亮灯程序即可,如果不能用中断,可以选择在计时程序中加入if (key==0)break,直接跳出子程序。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

7#
ID:282917 发表于 2018-2-10 19:59 | 只看该作者
扫描到按键按下以后,计时器开始计时,计时时间大概10ms一次,按键还是按着的,计数,满10
s就灯灭,如果中途扫到按键不安着了,关中断,灭灯

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

9#
ID:89515 发表于 2018-2-14 13:07 | 只看该作者
不知问题可有解决。你想一想按键按下为什么灯不灭。按键一直按下是会造成cpu时间堵塞的。这样常规的按键检测方式会有意想不到的后果。所以你有两种常用的方法可以解决,第一按键程序写为状态机的方式,但是你必须懂这种方式,第二把按键程序写成中断的方式,是定时器中断不是外部中断。状态机的方式可以在网上学习。定时器中断就很简单了,当主程序检测到按键按下,不要延时消除抖动,直接启动定时器。在定时器中断里对按键端口进行判断,如果端口为低电平就不用关闭定时器,反之关闭。这里你要按下多久,就多久关闭就行了。定时器的溢出时间可以是10毫秒级,这样不用浪费CPU资源.你可以做很多事情,就不要说改变LED状态了。状态机的方式与之有些类似,但学好了要强大很多。所有的程序都可以用。而且用好了都不会遇到CPU堵塞的情况

评分

参与人数 1黑币 +70 收起 理由
admin + 70 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

10#
ID:964852 发表于 2021-11-18 10:03 | 只看该作者
wulin 大神!膜拜
回复

使用道具 举报

11#
ID:554500 发表于 2021-11-18 10:55 | 只看该作者
//用定时器100ms调用一次
sbit key=P1^0;
void key_scan()
{
        static u8 i=0,n=0;
       
        if(key==0)
        {
                if(i==0)
                {
                        if(key==0&&n++>100) //100ms *100=10000ms=10s
                        {
                                i=1;
                                //灯灭
                        }
                }
        }
        else
        {
                i=0;
                n=0;
        }
}
回复

使用道具 举报

12#
ID:554500 发表于 2021-11-18 11:23 | 只看该作者


#include<reg52.h>
#include "LCD1602.H"
#define u8 unsigned char
#define u16 unsigned int
sbit LED=P2^0;
sbit KEY=P2^1;
bit Time_f=0;
void Timer0_init() //50毫秒@12.000MHz
{
  TMOD|=0x01;
TL0 = (65536-50000)%256;  //设置定时初始值
TH0 = (65536-50000)/256;  //设置定时初始值
TF0 = 0;  //清除TF0标志
TR0 = 1;  //定时器0开始计时
ET0=1;
EA=1;
}
void isr_timer0()interrupt 1  //定时器0中断服务子函数
{
TL0 = (65536-50000)%256;  //设置定时初始值
TH0 = (65536-50000)/256;  //设置定时初始值
Time_f=1;
}
//50ms调用一次
//短按灯亮,长按灯灭
void KEY_SCAN()
{
static u8 i=0,c=0;

if(KEY==0)
{
  if(i==0)
  {
   if(KEY==0&&c++>=200) //50ms*200=10000ms=10s
   {
    i=1;
    LED=1; //灯灭
   }
  }
}
else
{
  if(c>1&&c<200)
   LED=0; //灯亮
  
  i=0;
  c=0;
}
}
void main()
{

Timer0_init();
  while(1)
{
  if(Time_f)
  {
   Time_f=0;
   KEY_SCAN();
  }
}
}

51单片机定时器proteus仿真.zip

103.31 KB, 下载次数: 1

回复

使用道具 举报

13#
ID:123289 发表于 2021-11-18 12:53 | 只看该作者
要点如下:
1、按键确认:弹动处理,略。
2、按键边沿识别:通过【按键确认】后是0,是1,并与上次键值比较是否相同,达成【按键前沿确认】的目的。如按下=0,则上次为1,本次为0时,为前沿;如按下=1,则上次为0,本次为1时,为前沿。上次键值要做好标记。
3、用定时器计时:做个标记T,T=1 时计时器增加,T=0不计。
4、计时起动:【按键前沿确认】时置T=1。
5、计时器停止:当计时器增加达到10秒时,清T0。
6、显示:T=1时亮,T=0时灭。可以只有4、5、时变动一下。

记住:写程序最重要的是构思,逻辑上先要说得通!而后再据此写程序。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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