基于51单片机的液晶万年历设计论文带温度显示Word文档下载推荐.docx
《基于51单片机的液晶万年历设计论文带温度显示Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《基于51单片机的液晶万年历设计论文带温度显示Word文档下载推荐.docx(18页珍藏版)》请在冰豆网上搜索。
2.软件工作介绍
由于C语言功能丰富,表达能力和可移植能力强,而且操作方便,简单易懂,因此软件部分由C语言编写,程序的重点和难点是闰月的时间调整以及键盘对时间的调整,本程序还不是太完善,温度显示有规律性的微微闪烁,恳请老师指正。
否否
是是是
是是是
主程序流程图
设计总结
在制作的过程中,因为板子是在学校自己动手做的最小系统板,接插线还是比较简单的,难的是硬件的调试,因为理论与实践总是存在着差距,想出来的东西没有经过实践的检验是不可靠的,任何一个小小的疏忽大意都能导致失败。
比如说对hour,min,sec,day,moth的定义,一开始我用的unsignedchar,但是在调试减一时,减到零时再按下键盘就会出现乱码,几经调试,终于发现问题地所在并及时地解决了问题,之后再一次对硬件进行调试,终于成功了。
从这一方面来说,我认识到做要比说难得多,做的过程中必定有很多的阻碍,但是一定要慢慢来,一点一点地找出问题,再一点一点地解决它,这样的话,到达成功的彼岸也就仅仅是时间的问题了。
我通过这次设计,特别是通过对程序的编写,深层了解了单片机内部结构和外围器件的应用。
我学到的不仅仅是电子方面的知识,更重要的是,我学到了作为一名电子设计者所必需的心理素质,那就是——决心加上耐心!
附录1:
程序代码:
#include<
reg51.h>
#defineLcd_DataP0//定义数据端口
#define_TH0_TL0_(65536-50000)
#defineHI(_TH0_TL0_/256)//给高8位赋值
#defineLO(_TH0_TL0_%256)//给低8位赋值
#defineM20//(1000/50)1秒要20个中断的累计
charhour=0,min=0,sec=0,N=0,day=1,moth=1,week=7;
//初始化要显示的值
unsignedcharSEG_TAB[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
//0-9数字
unsignedintyear=8;
sbitRS=P2^5;
//定义和LCD的连接端口
sbitRW=P2^4;
sbitE=P2^3;
sbitBusy=P0^7;
sbitS3=P3^2;
//定义开关s3选择键
sbitS4=P3^3;
//s4加一键
sbitS5=P3^4;
//s5减一键
sbitDQ=P2^0;
//DS18B20
sbitspeak=P2^1;
//蜂鸣器警报
/***************************************************************************/
voiddelay1(unsignedintnum)//短延时函数
{
while(num--);
}
/******************************************************************************/
voidDelay(unsignedchart)//长延时函数,延时1MS*tS
unsignedchara;
while(--t!
=0)
{
for(a=0;
a<
125;
a++);
}
/*******************************************************************/
voidTimer0Init(void)//初始化定时器0程序
TMOD=0x01;
//设置模式1定时器0工作方式0
TH0=HI;
//给TH0,TL0赋初始值
TL0=LO;
TR0=1;
//启动定时器0
ET0=1;
//定时器中断开
EA=1;
//总中断开
voidRead_Busy(void)//读忙信号判断
do{
Lcd_Data=0xff;
RS=0;
RW=1;
E=0;
Delay
(2);
E=1;
}while(Busy);
/******************************************************************************/
voidWrite_Comm(unsignedcharlcdcomm)//写指令函数
{
Lcd_Data=lcdcomm;
RS=0;
RW=0;
E=0;
Read_Busy();
E=1;
voidWrite_Data(unsignedcharlcddata)//写数据函数
Lcd_Data=lcddata;
RS=1;
voidInit_LCD(void)//初始化LCD
Delay(400);
//稍微延时,等待LCD进入工作状态
Write_Comm(0x01);
//清显示
Write_Comm(0x02);
//光标归位
Write_Comm(0x38);
//8位2行5*8
Write_Comm(0x06);
//文字不动,光标右移
Write_Comm(0x0c);
//显示开/关,光标开闪烁开
Write_Comm(0x18);
//左移
/*******************************************************************************/
Init_DS18B20(void)//初始化ds1820
unsignedcharx=0;
DQ=1;
//DQ复位
delay1(8);
//稍做延时
DQ=0;
//单片机将DQ拉低
delay1(80);
//精确延时大于480us
//拉高总线
delay1(14);
x=DQ;
//稍做延时后如果x=0则初始化成功x=1则初始化失败
delay1(20);
/**********************************************************************************/
ReadOneChar(void)//读一个字节
unsignedchari=0;
unsignedchardat=0;
for(i=8;
i>
0;
i--)
DQ=0;
//给脉冲信号
dat>
>
=1;
DQ=1;
if(DQ)
dat|=0x80;
delay1(4);
return(dat);
WriteOneChar(unsignedchardat)//写一个字节
DQ=dat&
0x01;
delay1(5);
dat>
=1;
Read_Disp_Temperature(void)//读取并显示温度
unsignedinta=0,b=0,c=0,t=0;
floattt=0;
Init_DS18B20();
WriteOneChar(0xCC);
//跳过读序号列号的操作
WriteOneChar(0x44);
//启动温度转换
//跳过读序号列号的操作
WriteOneChar(0xBE);
//读取温度寄存器
a=ReadOneChar();
b=ReadOneChar();
t=b;
t<
<
=8;
t=t|a;
tt=t*0.0625;
t=tt*10+0.5;
//放大10倍输出并四舍五入
a=t/100;
//十位
b=t/10-a*10;
//个位
c=t-a*100-b*10;
//小数位
if((t>
=360)||(t<
=150))//温度报警范围
{speak=0;
}
elsespeak=1;
Write_Comm(0x8d);
//lcd显示温度
Write_Data(SEG_TAB[a]);
Write_Data(SEG_TAB[b]);
Write_Data('
.'
);
Write_Data(SEG_TAB[c]);
voidmain(void)//主函数--数字读取和计算
Init_LCD();
//初始化LCD
Timer0Init();
//初始化定时器0
Write_Comm(0x83);
//写入"
:
"
字符
Write_Data('
'
Write_Comm(0x86);
Write_Comm(0x89);
//温度提示字符
T'
e'
m'
p'
Write_Comm(0xc1);
//第二行首地址
20--"
字符
2'
0'
Write_Comm(0xc5);
-'
Write_Comm(0xc8);
Write_Comm(0xcb);
while
(1)
{
Read_Disp_Temperature();
//温度
if(S3==0)
delay1(10);
N++;
if(N>
6){N=0;
while(S3==0);
Write_Comm(0xcf);
Write_Data(SEG_TAB[N]);
//显示切换键位所示的位置N
//0:
秒,1:
分,2:
时,3:
日,4:
月,5:
年6:
星期
if(S4==0)//时间调整--加
if(S4==0)
if(N==1)
min++;
if(min==60)min=0;
Write_Comm(0x84);
Write_Data(SEG_TAB[min/10]);
Write_Comm(0x85);
Write_Data(SEG_TAB[min%10]);
if(N==2)
hour++;
if(hour==24)hour=0;
Write_Comm(0x81);
Write_Data(SEG_TAB[hour/10]);
Write_Comm(0x82);
Write_Data(SEG_TAB[hour%10]);
if(N==3)
day++;
if(moth==2&
&
(year%4==0)&
day==30)day=1;
//闰年2月天数计算
(year%4!
=0)&
day==29)day=1;
//平年2月
if((moth==4||moth==6||moth==9||moth==11)&
day==31)day=1;
//4,6,9,11月计算
if(day==32)day=1;
//1,3,5,7,8,10,12月天数计算
Write_Comm(0xC9);
Write_Data(SEG_TAB[day/10]);
Write_Comm(0xCa);
Write_Data(SEG_TAB[day%10]);
if(N==4)
moth++;
if(moth==13)moth=1;
Write_Comm(0xc6);
Write_Data(SEG_TAB[moth/10]);
Write_Comm(0xc7);
Write_Data(SEG_TAB[moth%10]);
if(N==5)
year++;
if(year==51)year=0;
Write_Comm(0xc3);
Write_Data(SEG_TAB[year/10]);
Write_Comm(0xc4);
Write_Data(SEG_TAB[year%10]);
if(N==6)
{
week++;
if(week==8)week=1;
Write_Comm(0xcc);
}
while(S4==0);
}
if(S5==0)//时间调整--减
if(S5==0)
min--;
if(min<
0){min=59;
{hour--;
if(hour<
0){hour=23;
{day--;
if(moth==2&
day<
1)day=29;
1)day=28;
1)day=30;
if(day<
1)day=31;
{moth--;
if(moth==0){moth=12;
{year--;
if(year<
0){year=50;
if(N==6)
week--;
if(week==0)week=7;
Write_Data(SEG_TAB[week]);
while(S5==0);
}
/**************************************************************************/
voidIsrTimer0(void)interrupt1using1//定时器0中断服务程序
staticunsignedcharcount=0;
//定义静态变量count
TR0=0;
//时间误差调整
TL0+=(_TH0_TL0_+9)%256;
TH0+=(_TH0_TL0_+9)/256+(char)CY;
count++;
if(count==M)//1秒种时间到
count=0;
sec++;
if(sec==60)//1分钟时间到
{
min++;
sec=0;
if(min==60)//1小时时间到
hour++;
min=0;
if(hour==24)//24小时时间到
{day++;
week++;
hour=0;
min=0;
sec=0;
if(week==8)
{week=1;
}
if((moth==2&
day==30)||(moth==2&
day==29)||((moth==4||moth==6||moth==9||moth==11)&
day==31)||(day==32))
{//一个月到
moth++;
day=1;
if(moth==13)//一年到
{year++;
moth=1;
}
}
}
//时间显示
Write_Comm(0x82);
Write_Comm(0x85);
Write_Comm(0x86);
Write_Comm(0x87);
Write_Data(SEG_TAB[sec/10]);
Write_Comm(0x88);
Write_Data(SEG_TAB[sec%10]);
Write_Comm(0x8f);
Write_Data('
Write_Comm(0xc5);
Write_Co