本文主要是介绍基于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; //给定时器赋初值,定时1msTL0=0X18; ET0=1;//打开定时器0中断允许EA=1;//打开总中断TR0=1;//打开定时器
}void Int0Configuration() //外部中断0初始化
{IT0=1;//跳变沿出发方式(下降沿)EX0=1;//打开INT0的中断允许。EA=1;//打开总中断
}void main()
{Timer0Init();UsartConfiguration();Int0Configuration();//p3.2LcdInit();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(); //消除抖动 一般大约10msif(k1==0) //再次判断按键是否按下{choose++; //调要选的位数if(choose==6){choose=0;} }while(!k1); //检测按键是否松开}if(k2==0) //检测按键K1是否按下{ Delay10ms(); //消除抖动 一般大约10msif(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(); //消除抖动 一般大约10msif(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);}
}
//定时器中断0void Timer0() interrupt 1
{static u16 us;TH0=0XFC; //给定时器赋初值,定时1msTL0=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; //设置为工作方式1TMOD|=0X20; //设置计数器工作方式2PCON|=0X80; //波特率加倍TH1=0XF3; //计数器初始值设置,注意波特率是4800的TL1=0XF3;TR1=1; //打开计数器
}
lcd.h和temp.h网上有的是就不发了
仿真效果
显示还算凑活,调值啥的也正常,缺点是温度阈值不可调(懒。。),按键也不太稳,实际意义。。零点几吧。。。。
溜了,下次有缘再见!
bia ! bia !
这篇关于基于51单片机的温度计(外加电子时钟)纯纯纯小白自娱之作,大佬勿进的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!