基于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 !