2301_79946397 2023-10-15 13:27 采纳率: 87.5%
浏览 26
已结题

51单片机按键切换流水灯和时钟

我想搞一个按键切换在初始状态流水灯按一下到双闪灯再按一下到时钟,可是之中如果用延时函数会导致CPU不能运行很多事情造成卡顿,利用中断的话定时检测的时间又不一样,我试着编译了代码但发现运行很卡顿,希望能解答

img

img

img

img

img

  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-10-15 16:19
    关注

    【相关推荐】



    • 请看👉 :自己动手写CPU(4)解决流水线数据相关+逻辑、移位操作和空指令的实现
    • 除此之外, 这篇博客: 基于51单片机的恒温箱水温温度控制系统报警器方案原理图设计中的 系统软件设计 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:

      程序流程图
      在这里插入图片描述

      #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
      #include<stdio.h>
      #include "18b20.h"
      #include "1602.h"
      #include "delay.h"
      
      #define SETDOWN 0x01
      #define SETUP 0x02
      
      sbit key1=P2^0;	//引脚定义
      sbit key2=P2^1;
      sbit key3=P2^2;
      
      sbit relay_jiare=P1^0;
      sbit relay_zhileng=P1^1;
      sbit buzzer=P1^4;
      
      unsigned int setL= 20;         //上限
      unsigned int setH= 50;        //下限
      unsigned char DisFlag=0;		//更新显示标志
      unsigned char SetFlag=0;		//设置参数标志
      
      unsigned long time2ms=0;	//定时计数
      unsigned int buzLater=0;  //蜂鸣器计时报
      
      int temp1;						//读取温度初始值
      float temperature;				//实际温度值
      unsigned char ReadTempFlag=0;//定义读时间标志
      
      char dis0[16];//定义显示区域临时存储数组
      char dis1[16];//定义显示区域临时存储数组
      
      unsigned char Num=0;	 //计数
      
      void CheckKey(void);
      void Init_Timer0(void);//定时器初始化
      
      void main (void)
      {                  
      	relay_jiare=0;
      	relay_zhileng=0;
       	buzzer=0;
      
      	Init_Timer0();
      	LCD_Init();           //初始化液晶
      	DelayMs(200);          //延时有助于稳定
      	LCD_Clear();          //清屏
      
      	relay_jiare=1;
      	relay_zhileng=1;
       	buzzer=1;
      
      	while (1)         //主循环
      	{
      		CheckKey();			  //检测按键
      		if(ReadTempFlag==1)		//读取温度标志
      		{
      			ReadTempFlag=0;
      			temp1=ReadTemperature();	//读取温度
      			temperature=(float)temp1*0.0625;	  //温度值转换
      		}
      		if(DisFlag==1)	
      		{
      			DisFlag=0;
      			if((temperature>0)&&(temperature<150))
      			{
      				sprintf(dis0,"Temp:%4.1f C",temperature);//打印温度值
      				LCD_Write_String(0,0,dis0);//显示第二行
      				LCD_Write_Char(9,0,0xdf);//写入温度右上角点
      				
      				if(temperature<setL)	 //温度过低
      				{
      					relay_jiare=0;	//开启升温 关闭降温
      					relay_zhileng=1;
      				}
      				else if((temperature)>setH)  		//温度超高
      				{
      					relay_jiare=1;	//关闭升温 开启降温
      					relay_zhileng=0;
      				}
      				else	 		//正常温度
      				{
      					relay_jiare=1;	//关闭升温 关闭降温
      					relay_zhileng=1;
      					buzLater=0;
      				}
      				if(buzLater>=60)//正常清零 否则过高过低都会累加 超过1min
      				{buzzer=0;}	//打开蜂鸣器				
      				else
      				{buzzer=1;}	//关闭蜂鸣器
      							
      			}
      			sprintf(dis1," %02d-- %02d       ",setL,setH);
      			LCD_Write_String(0,1,dis1);	//初始化显示 
      			
      			if(SetFlag == 0)//按键设置标志
      			{
      				LCD_Write_Char(0,1,' ');LCD_Write_Char(5,1,' ');//更新显示标志
      			}
      			else if(SetFlag == 1)//按键设置标志
      			{
      				LCD_Write_Char(0,1,'S');LCD_Write_Char(5,1,' ');//更新显示标志
      			}			
      			else if(SetFlag == 2)//按键设置标志
      			{
      				LCD_Write_Char(0,1,' ');LCD_Write_Char(5,1,'S');//更新显示标志
      			}	
      		}
      	}
      }
      
      void CheckKey(void)
      { 
      	static unsigned  char rekey =0;
      	if((key1==0)||(key2==0)||(key3==0))		 //检测到按键按下
      	{
      		DelayMs(10);   //小抖动
      		if(rekey==0)
      		{
      			if(key1==0)    //检测是否按下
      			{
      				rekey=1;
      				SetFlag++;//设置标志
      				if(SetFlag >= 3) SetFlag = 0;
      			}	
      			else if(key2==0)//设置值键
      			{
      				rekey=1;
      				if(SetFlag==1)      //处于设置1
      				{
      					if(setL > 0 )
      					{setL=setL-1;}
      				}
      				else if(SetFlag==2)//处于设置2
      				{
      					if(setH > 0)
      					{setH=setH-1;}
      				}						
      			}
      			else if(key3==0)//设置值键
      			{
      				rekey=1;
      				if(SetFlag==1)      //处于设置1
      				{
      					if(setL < 99 )
      					{setL=setL+1;}
      				}
      				else if(SetFlag==2)//处于设置2
      				{
      					if(setH < 99 )
      					{setH=setH+1;}
      				}				
      			}
      		}
      	}
      	else
      	{
      	rekey=0;    //防止重复检测到按键
      	}
      }
      
      
      /*------------------------------------------------
                          定时器初始化子程序
      ------------------------------------------------*/
      void Init_Timer0(void)
      {
      	TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
      	//TH0=0x00;	      //给定初值
      	//TL0=0x00;
      	EA=1;            //总中断打开
      	ET0=1;           //定时器中断打开
      	TR0=1;           //定时器开关打开
      }
      /*------------------------------------------------
                       定时器中断子程序
      ------------------------------------------------*/
      void Timer0_isr(void) interrupt 1 
      {
      	TH0=(65536-20000)/256;		  //重新赋值 20ms
      	TL0=(65536-20000)%256;
      	time2ms++;
      
      	if(time2ms%10==0)	//更新显示
      	{
      		DisFlag=1;
      		if(time2ms%50==0)	 	//读取温度
      		{
      			ReadTempFlag=1; //读标志位置1	
      			if(buzLater<200)buzLater++;
      		}
      	}
      }
      
      
      
      

      .

      链接:

      https://pan.baidu.com/s/1XFejOp1NAFQDVMRlZGxdZQ
      提取码:04hq

      .


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 10月24日
  • 已采纳回答 10月16日
  • 修改了问题 10月15日
  • 修改了问题 10月15日
  • 展开全部