基于51单片机的温度计(外加电子时钟)纯纯纯小白自娱之作,大佬勿进

基于51单片机的温度计(外加电子时钟)

因为学校微机课设的要求,做了一个这么玩意儿,实属小白自娱,大佬勿侃!!
闲话不多说,Let us go!

先上Proteus仿真图

在这里插入图片描述
一上午Proteus速成结果(垃圾的一批。。勿喷)
这里选用的式DS18B20温度传感器+lcd1604显示,左边的电机纯属瞎加,驱动芯片用L298N
!!!该图仅限于仿真,不可用于实际连接!!!

功能

系统实时显示温度值和年月日时分值,当温度高于既定温度,红灯亮,电机运转(相当于一个小风扇);当温度低于既定温度,蓝灯亮;
按键功能:
k1:负责值加一
k2:负责决定需要修改的位(年月日时分秒)
k3:负责总控制标志位
k4:负责值减一

贴一下main.c代码

前情提示,因为速成且任务量着实太小,所以全让我塞一个c文件了,整洁度啊,语法水平啊,全都是最low!!!见谅。。

//      ┏┛ ┻━━━━━┛ ┻┓
//      ┃       ┃
//      ┃   ━   ┃
//      ┃ ┳┛   ┗┳ ┃
//      ┃       ┃
//      ┃   ┻   ┃
//      ┃       ┃
//      ┗━┓   ┏━━━┛
//        ┃   ┃   神兽保佑
//        ┃   ┃   代码无BUG!
//        ┃   ┗━━━━━━━━━┓
//        ┃           ┣┓
//        ┃             ┏┛
//        ┗━┓ ┓ ┏━━━┳ ┓ ┏━┛
//          ┃ ┫ ┫   ┃ ┫ ┫
//          ┗━┻━┛   ┗━┻━┛
#include<reg51.h>
#include"lcd.h"
#include"temp.h"
sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;
sbit ENA=P1^2;
sbit IN2=P1^1;
sbit IN1=P1^0;
sbit led0=P2^0;
sbit led1=P2^1;

typedef unsigned long u32;
typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

u16 second=0,min=0,hour=0,date=1,month=1;
u16 year=2000;	  
u8 start_flag=1;           //总控制位
u16 shuzu[6];

static u8 choose;  //选择位

void LcdDisplay(int);
void UsartConfiguration();
void Delay10ms(void);
void keypros(void);
void LcdDisplay();

void Timer0Init()
{
	TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

	TH0=0XFC;	//给定时器赋初值,定时1ms
	TL0=0X18;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器			
}

void Int0Configuration()	//外部中断0初始化
{

	IT0=1;//跳变沿出发方式(下降沿)
	EX0=1;//打开INT0的中断允许。
	EA=1;//打开总中断	
}



void main()
{
     
	Timer0Init();
	UsartConfiguration();
	Int0Configuration();//p3.2
	LcdInit();
	
	 while(1)
	 {

		if(start_flag==1)
	 {
		  
	 	  if(min==60){hour++;min=0;}
		  if(hour==24){hour=0;date++;}
		  if(year%4==0)
		  {
		  if(month==2)
		  {
		  		if(date>=30)
		  		{
		 		 month++;
				 date=1;
		 		 }
		  }
		  else if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
		  {
		  		if(date==32)
				{
				date=1;
				month++;
				}
		  }
		  else 
		  {
		  		if(date==31)
				{
				date=1;
				month++;
				}
		  }
		  
		  }
		  	 
		  else
		  {
		  if(month==2)
		  {
		  		if(date>=29)
		  		{
		 		 month++;
				 date=1;
		 		 }
		  }
		  else if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
		  {
		  		if(date==32)
				{
				date=1;
				month++;
				}
		  }
		  else 
		  {
		  		if(date==31)
				{
				date=1;
				month++;
				}
		  }
		  }	 //判断是否闰月;
		  if(month==13){month=1;year++;}
	}//正常时钟功能;
	  else
	  {
	  shuzu[0]=	 year;
	  shuzu[1]=	 month;
	  shuzu[2]=	 date;
	  shuzu[3]=	 hour;
	  shuzu[4]=	 min;
	  shuzu[5]=	 second;

	  if(k1==0)		  //检测按键K1是否按下
	{	
		Delay10ms();   //消除抖动 一般大约10ms
		if(k1==0)	 //再次判断按键是否按下
		{
		choose++;							  //调要选的位数
		if(choose==6){choose=0;}	
		}
		while(!k1);	 //检测按键是否松开
	}
	if(k2==0)		  //检测按键K1是否按下
	{	
		Delay10ms();   //消除抖动 一般大约10ms
		if(k2==0)	 //再次判断按键是否按下
		{
		
			shuzu[choose]=shuzu[choose]+1;								  //加数
			switch(choose){												//防止超出上限值
				case 0:break;
				case 1:if(shuzu[choose]==13){shuzu[choose]=0;}break;
				case 2:if(shuzu[choose]==32){shuzu[choose]=1;}break;
				case 3:if(shuzu[choose]==13){shuzu[choose]=0;}break;
				case 4:if(shuzu[choose]==61){shuzu[choose]=0;}break;	
				case 5:if(shuzu[choose]==61){shuzu[choose]=0;}break;
			
			}

		}
		while(!k2);	 //检测按键是否松开
	}
	if(k4==0)		  //检测按键K1是否按下
	{	
		Delay10ms();   //消除抖动 一般大约10ms
		if(k4==0&&shuzu[choose]!=0)	 //再次判断按键是否按下
		{
		
			shuzu[choose]=shuzu[choose]-1;				   //减数且到0后就减不动了;
			

		}
		while(!k4);	 //检测按键是否松开
	}
	  
	     year=shuzu[0];
	  	 month=shuzu[1];
	  	 date=shuzu[2];
	  	 hour=shuzu[3];
	  	 min=shuzu[4];
	  	 second=shuzu[5];
	  
	  }
	
	  
      
	 
	LcdWriteCom(0x80+0X40);
    LcdWriteData('0'+date/10);
	LcdWriteData('0'+date%10);
	LcdWriteData('-');
	LcdWriteData('0'+hour/10);
	LcdWriteData('0'+hour%10);
	LcdWriteData('-');
	LcdWriteData('0'+min/10);
	LcdWriteData('0'+min%10);
	LcdWriteData('-');
	LcdWriteData('0'+second/10);
	LcdWriteData('0'+second%10);
	LcdDisplay(Ds18b20ReadTemp());
	LcdWriteCom(0x87);	//写地址 80表示初始地址
	LcdWriteData('C'); 
	LcdWriteCom(0x89);
    LcdWriteData('0'+year/1000);
	LcdWriteData('0'+year%1000/1000);
	LcdWriteData('0'+year%100/10);
	LcdWriteData('0'+year%10);
	LcdWriteData('-');
	LcdWriteData('0'+month/10);
	LcdWriteData('0'+month%10);
	
	 }
}
//定时器中断0


void Timer0() interrupt 1
{
	static u16 us;
	TH0=0XFC;	//给定时器赋初值,定时1ms
	TL0=0X18;
	us++;
	if(us==1000)
	{
		us=0;
		second++;
		if(second==60){second=0;min++;}	
	}	
}

//外部中断0
void Int0() interrupt 0		 
{
	Delay10ms();
	if(k3==0)
	{
	start_flag=~start_flag;    //总开始标志,1为校正状态,2为正常运行;	
	TR0=~TR0;	//控制定时器1;
	}
}


void Delay10ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}

void LcdDisplay(int temp) 	 //lcd显示
{
    
  	unsigned char i, datas[] = {0, 0, 0, 0, 0}; //定义数组
	float tp;  
	if(temp< 0)				//当温度值为负数
  	{
	  	LcdWriteCom(0x80);		//写地址 80表示初始地址
		SBUF='-';//将接收到的数据放入到发送寄存器
		while(!TI);			         //等待发送数据完成
		TI=0;						 //清除发送完成标志位
	    LcdWriteData('-');  		//显示负
		//因为读取的温度是实际温度的补码,所以减1,再取反求出原码
		temp=temp-1;
		temp=~temp;
		tp=temp;
		temp=tp*0.0625*100+0.5;	
		//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
		//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
		//算由?.5,还是在小数点后面。
 
  	}
 	else
  	{			
	  	LcdWriteCom(0x80);		//写地址 80表示初始地址
	    LcdWriteData('+'); 		//显示正
		SBUF='+';//将接收到的数据放入到发送寄存器
		while(!TI);			         //等待发送数据完成
		TI=0;						 //清除发送完成标志位
		tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
		//如果温度是正的那么,那么正数的原码就是补码它本身
		temp=tp*0.0625*100+0.5;	
		//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
		//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
		//算加上0.5,还是在小数点后面。
	}
	datas[0] = temp / 10000;
	datas[1] = temp % 10000 / 1000;
	datas[2] = temp % 1000 / 100;
	datas[3] = temp % 100 / 10;
	datas[4] = temp % 10;

	LcdWriteCom(0x81);		  //写地址 80表示初始地址
	LcdWriteData('0'+datas[0]); //百位 
	SBUF = '0'+datas[0];//将接收到的数据放入到发送寄存器
	while (!TI);			         //等待发送数据完成
	TI = 0;
	
	LcdWriteCom(0x82);		 //写地址 80表示初始地址
	LcdWriteData('0'+datas[1]); //十位
	SBUF = '0'+datas[1];//将接收到的数据放入到发送寄存器
	while (!TI);			         //等待发送数据完成
	TI = 0;

	LcdWriteCom(0x83);		//写地址 80表示初始地址
	LcdWriteData('0'+datas[2]); //个位 
	SBUF = '0'+datas[2];//将接收到的数据放入到发送寄存器
	while (!TI);			         //等待发送数据完成
	TI = 0;

	LcdWriteCom(0x84);		//写地址 80表示初始地址
	LcdWriteData('.'); 		//显示 ‘.’
	SBUF = '.';//将接收到的数据放入到发送寄存器
	while (!TI);			         //等待发送数据完成
	TI = 0;

	LcdWriteCom(0x85);		 //写地址 80表示初始地址
	LcdWriteData('0'+datas[3]); //显示小数点  
	SBUF = '0'+datas[3];//将接收到的数据放入到发送寄存器
	while (!TI);			         //等待发送数据完成
	TI = 0;

	LcdWriteCom(0x86);		 //写地址 80表示初始地址
	LcdWriteData('0'+datas[4]); //显示小数点 
	SBUF = '0'+datas[4];//将接收到的数据放入到发送寄存器
	while (!TI);			         //等待发送数据完成
	TI = 0;

	 if(temp>=4500){
	 led0=0;
	 ENA=1;
	 IN1=0;
	 IN2=1;
	 }				  //警报放在这里,超过45摄氏度,红色led灯亮;外加一个电风扇(直流电机驱动的) ;                  
	 else{            //在显示函数里加判断语句估计除我也没谁了。。。                                            
	 led0=1;
	 ENA=0;
	 }
	 if(temp<=3500){		  //低温警告   对应蓝灯
	  led1=0;	 
	 }
	 else{
	 led1=1;
	 }
	 
}

void UsartConfiguration()
{
	SCON|=0X50;			//设置为工作方式1
	TMOD|=0X20;			//设置计数器工作方式2
	PCON|=0X80;			//波特率加倍
	TH1=0XF3;				//计数器初始值设置,注意波特率是4800的
	TL1=0XF3;
	TR1=1;					//打开计数器
}

lcd.h和temp.h网上有的是就不发了

仿真效果

*强调文本* _强调文本_显示还算凑活,调值啥的也正常,缺点是温度阈值不可调(懒。。),按键也不太稳,实际意义。。零点几吧。。。。

溜了,下次有缘再见!

bia ! bia !

  • 7
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值