数码之家

 找回密码
 立即注册
搜索
查看: 1219|回复: 18

[C51] 帮我看下这个程序到底哪里有问题,为什么(key1==1)定时器还在计时呢?

[复制链接]
发表于 2022-5-4 14:32:05 | 显示全部楼层 |阅读模式
50家元
我要的的是(key1==0) 当按键按下LED长亮,(key1==1)按键松开LED亮10秒钟,然后熄灭。

问题来了,(key1==0) 按键按下LED亮,为什么(key1==1)定时器还在计时呢?到底哪里有问题,按道理(key1==1)按键松开才会开始计时啊!


#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit  key1=P3^4;//用P1.0做按键1输入

sbit  led1=P3^3;//定义输出1



void delay(uint n) {//
    uint aa,bb;

         for(aa=0;aa<n;aa++){
        for(bb=0;bb<850;bb++)
            ;
}
}
void main(void)
{
  while(1)
    {


if(key1==0)
          {
            delay(0);//如果按键按下就延时30毫秒去抖动再判断
             if(key1==0)
               {

                  led1 = 0;//输出取反

                  while(!key1);//按键不放就死循环


}                                                           


  }   






                                          
                 if(key1==1)
          {
             delay(0);//如果按键松开就延时30毫秒去抖动再判断

               {
                 if(key1==1)  
                                
                                        led1 = 0;//输出取反
                  delay(9999);
                     led1 = 1;//输出高电平            
            while(key1==1);//按键抬起就不循环
                                                }                                                           
          }



     }
}

最佳答案

查看完整内容

这样是不是更好点
发表于 2022-5-4 14:32:06 | 显示全部楼层
这样是不是更好点
  1. #include <stc15.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit  key1=P3^4;//用P1.0做按键1输入
  5. sbit  led1=P3^3;//定义输出1
  6. uint x=0;

  7. void Timer0Init(void)                //5毫秒@11.0592MHz
  8. {
  9.         AUXR |= 0x80;                //定时器时钟1T模式
  10.         TMOD &= 0xF0;                //设置定时器模式
  11.         TL0 = 0x00;                //设置定时初始值
  12.         TH0 = 0x28;                //设置定时初始值
  13.         TF0 = 0;                //清除TF0标志
  14.         TR0 = 1;                //定时器0开始计时
  15. }
  16. void main(void)
  17. {
  18.   led1=1;
  19.         key1=1;
  20.         Timer0Init();
  21.         ET0=1;
  22.         EA=1;
  23.         while(1)
  24.     {
  25.                         if(!key1)
  26.                         {
  27.                                 led1=0;
  28.                           x=0;
  29.                         }
  30.                
  31.                         else {
  32.                                 if(x>2000)
  33.                                 {
  34.                                 x=0;
  35.                                 led1=1;
  36.                                 }
  37.                         }
  38.                 }
  39.         }
  40. void time0() interrupt 1
  41. {x++;}
复制代码
回复

使用道具 举报

发表于 2022-5-4 17:16:18 | 显示全部楼层
直接把.c文件传上来,你这格式看着好别扭
回复

使用道具 举报

发表于 2022-5-4 18:28:31 | 显示全部楼层
如果 delay(0) 是 30ms,那么 delay(9999)实际只有 450 ms。同时程序在 “ while(key1==1);//按键抬起就不循环  ” 里循环等待
回复

使用道具 举报

发表于 2022-5-4 18:34:04 来自手机浏览器 | 显示全部楼层
按键送开的代码放到按下按键的代码里。这样只有在按键按下后才触发这两个判断。
你现在分开写,那按键要么松开要么按下,任何时候都在执行其中一个代码了。
回复

使用道具 举报

发表于 2022-5-4 18:37:07 来自手机浏览器 | 显示全部楼层
鉴于你逻辑混乱,建议你先写伪代码出来的,确认逻辑上没问题再写具体代码。
回复

使用道具 举报

发表于 2022-5-4 18:44:08 | 显示全部楼层
好像没啥问题,除了,上电就会亮一次,
回复

使用道具 举报

 楼主| 发表于 2022-5-4 19:11:36 | 显示全部楼层
ploestar 发表于 2022-5-4 18:58
这样是不是更好点

代码有问题 报错
回复

使用道具 举报

 楼主| 发表于 2022-5-4 19:14:28 | 显示全部楼层
jackenjoy 发表于 2022-5-4 18:28
如果 delay(0) 是 30ms,那么 delay(9999)实际只有 450 ms。同时程序在 “ while(key1==1);//按键抬起就不 ...

delay(9999) 每个单片机频率都不一样 我数了差不多9秒多一点
回复

使用道具 举报

发表于 2022-5-4 19:21:02 | 显示全部楼层
看的头昏脑胀的。。
回复

使用道具 举报

发表于 2022-5-4 21:12:22 | 显示全部楼层
感觉key1==1的判断用else靠谱,另外key1的状态判断为真后没有关闭定时器计数的命令怎么才让定时器停止计时呢,开启定时器(定时计数器T0)时需要TR0=1;而关闭定时器则需要TR0=0;例如:

if(key1==0)
          {
            delay(0);//如果按键按下就延时30毫秒去抖动再判断
             if(key1==0)
               {
TR0=0;//关闭定时计数器
n=0;//计数变量清零
                  led1 = 0;//输出取反

                  while(!key1);//按键不放就死循环


}  
TR0=1;//状态结束后再开启计时            
回复

使用道具 举报

 楼主| 发表于 2022-5-4 21:50:24 | 显示全部楼层
慕名而来 发表于 2022-5-4 21:12
感觉key1==1的判断用else靠谱,另外key1的状态判断为真后没有关闭定时器计数的命令怎么才让定时器停止计时 ...

n=0;//计数变量清零  这个报错 ,TR0=0;//关闭定时计数器  在单片机上运行了一下 计时器还是在运行
回复

使用道具 举报

发表于 2022-5-4 22:35:27 | 显示全部楼层
楼主这个程序单片机就做了个定时,其实最好用定时器,首先程序更稳定今后还可以程序移植,虽然这个程序只是点小bug但不利于良好编程习惯的养成。
回复

使用道具 举报

发表于 2022-5-4 23:36:38 来自手机浏览器 | 显示全部楼层
yyou58 发表于 2022-5-4 19:11
代码有问题 报错

你没有头文件吧
回复

使用道具 举报

 楼主| 发表于 2022-5-5 07:52:57 | 显示全部楼层
试了一下可以正常运行 x=0; 这句是什么意思啊
回复

使用道具 举报

发表于 2022-5-11 22:28:14 | 显示全部楼层
yyou58 发表于 2022-5-4 21:50
n=0;//计数变量清零  这个报错 ,TR0=0;//关闭定时计数器  在单片机上运行了一下 计时器还是在运行 ...

我的回复是基于定时器定时的控制模式,如果用软件延时函数来实现楼主的按键控制效果请参考下列代码:
1.代码用于演示楼主希望达成的效果。
2.程序下载后LED灯眨动一下后保持熄灭状态。
3.按下按键不松开时LED灯常亮。
4.松开按键后,LED短暂熄灭后再次亮起并保存点亮2秒钟后熄灭并保持熄灭状态。此后等待按键的再次操作。
5.你的代码忽略了主循环的死循环状态,在死循环状态下代码永远运行在按键抬起状态下,此时你只能感知到LED灯的点亮状态,而10秒后的熄灭状态会一闪而逝无法感知的。
6.我的代码是用STC12C5A60S2单片机测试的,如果是其他单片机请重新编写延时函数。
7.如果你仍然有疑问请在代码的注释中查找答案。

  1. #include<reg52.h>
  2. #include <intrins.h>//引用此头文件为了使用nop函数
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit key=P3^4;//定义P5.4为按键状态采集端口
  6. sbit led1=P3^3;//定义P1.4口控制LED灯,本例LED灯为低电平点亮高电平熄灭的控制模式
  7. //====(value)ms@12MHz=======================================================
  8. //此函数仅适合STC12系单片机,换用其他单片机时请重新编写,否则延时时间严重不准
  9. void delay_ms(uint value)
  10. {
  11.     uchar i,j;
  12.     while(value>0)
  13.     {
  14.         _nop_();
  15.         _nop_();
  16.         i = 12;
  17.         j = 168;
  18.         do
  19.         {
  20.             while (--j);
  21.         }
  22.         while (--i);
  23.         value--;
  24.     }
  25. }
  26. //===================================
  27. void main()
  28. {
  29.     uchar flag=0;//设置一个标志变量并初始化,如果没有标志控制、程序将循环运行LED为常亮状态
  30.     led1=1;//必须在此处初始化控制端口、否则可能会出现LED不可控或控制紊乱现象
  31.     while(1)
  32.     {
  33.         if(key==0)
  34.         {
  35.             delay_ms(20);//等一等
  36.             if(key==0)//如果按键属实被按下了
  37.             {
  38.                 flag=1;//按键按下后标志状态置位
  39.                 led1=0;//按键不松开LED就一直发光
  40.                 while(!key);
  41.             }
  42. //以下两行代码用来演示开关的切换状态
  43. //如果不加入以下两句则LED将保存点亮无法感知控制状态的转变
  44. //实际使用时请去除以下两行代码
  45.             led1=1;//按键松开后LED关闭0.5S
  46.             delay_ms(500);
  47.         }
  48.         if((key==1)&&(flag==1))
  49.         {
  50.             flag=0;//按键松开后清除标志状态
  51.             led1=0;//点亮LED
  52.             delay_ms(2000);//为了快速看到演示效果,无按键按下时LED仅仅点亮2秒钟
  53.             led1=1;//如果无按键按下、LED点亮10秒后熄灭
  54.         }
  55.     }
  56. }
复制代码


回复

使用道具 举报

发表于 2022-5-13 11:49:19 | 显示全部楼层
这样是不是也可以
  1. void main()
  2. {
  3.   while(1)
  4.     {
  5.                 if(key1==0)
  6.                 {
  7.                         led1=0;                //led亮
  8.                 }
  9.                 if(key1==1)
  10.                         Delay(10);        //10秒
  11.                         led1=1;        //led灭
  12.                         EA=0;        //关闭总中断
  13.         }
  14. }
复制代码
回复

使用道具 举报

发表于 2022-5-14 11:35:04 | 显示全部楼层
==
  while(!key1);//按键不放就死循环
这里 ,只要按键抖动一下就跳出死循环了,就进行下一步程序了
,,在按键两端加一个100NF电容,硬件去抖动,
或者程序修改,去抖动方式,
回复

使用道具 举报

发表于 2022-5-14 15:44:39 | 显示全部楼层
mtt661 发表于 2022-5-13 11:49
这样是不是也可以

好方法,简单明了、学习了。另外他没用到定时器,所有EA=0没啥用的。
回复

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-5-21 11:12 , Processed in 0.187201 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

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