摘要在寒假期间我用一周时间完成了这个液晶万年历,它可以显示年月日、时分秒、以及温度(可上下限报警),可以对时间进行加一或减一调整,并加入了闰、平年时间调整,方便可行,已经调试成功考虑到成本和方便,本作品采用了STC89c52和DS18B20,计时用的是51单片机自带的十六位定时器/计数器T0,尽管对时间进行了误差调整但是还是有一定的误差,考虑到学校后改用DS1302时钟芯片,进一步减小误差温度显示精度达到0.1摄氏度关键词: 单片机 DS18B20 万年历 温度1. 硬件工作介绍(1)上电自动复位及手动复位电路 STC89c52单片机的RST端外部复位有两种操作方式:上电自动复位和按键手动复位本设计用上电自动复位以及手动复位下结合的方式外接电路(见附图)2)时钟振荡电路作品中采用12M晶振,其连接方法如图所示,其中电容的值都为22pF3)1602液晶显示接口1602采用标准的16脚接口(见附图),其中:第1脚:GND为地电源第2脚:VCC接5V正电源第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:RW为读写信号线,高电平时进行读操作,低电平时进行写操作当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令第7~14脚:D0~D7为8位双向数据线 第15脚:VCC第16:GND(4)键盘键盘是通过S3(P3.2),S4(p3.3),S5(p3.4)对时钟进行调整,其S3选择要调整的对象如时,分,日,月等等,并在液晶屏上显示所选的对象S4对所选中的对象进行加一调整,而S5对所选对象进行减一调整5)蜂鸣器 对温度进行测量,高低温超限报警,正常温度在15.0-36.0摄氏度,超过最高或低于最低温度就会鸣叫报警2. 软件工作介绍 由于C语言功能丰富,表达能力和可移植能力强,而且操作方便,简单易懂,因此软件部分由C语言编写,程序的重点和难点是闰月的时间调整以及键盘对时间的调整,本程序还不是太完善,温度显示有规律性的微微闪烁,恳请老师指正开始 LCD初始化 T0初始化 时间、温度显示 S3按下否? S4按下否? S5按下否? 否 否是 是 是 时间加一 N加一,选择调整对象 时间减一 否 否到最大值否? N=6否?到最小值否? 是 是 是 时间清零 N清零 时间清零 主程序流程图设计总结在制作的过程中,因为板子是在学校自己动手做的最小系统板,接插线还是比较简单的,难的是硬件的调试,因为理论与实践总是存在着差距,想出来的东西没有经过实践的检验是不可靠的,任何一个小小的疏忽大意都能导致失败。
比如说对 hour, min , sec,day, moth的定义,一开始我用的unsigned char ,但是在调试减一时,减到零时再按下键盘就会出现乱码,几经调试,终于发现问题地所在并及时地解决了问题,之后再一次对硬件进行调试,终于成功了从这一方面来说,我认识到做要比说难得多,做的过程中必定有很多的阻碍,但是一定要慢慢来,一点一点地找出问题,再一点一点地解决它,这样的话,到达成功的彼岸也就仅仅是时间的问题了我通过这次设计,特别是通过对程序的编写,深层了解了单片机内部结构和外围器件的应用我学到的不仅仅是电子方面的知识,更重要的是,我学到了作为一名电子设计者所必需的心理素质,那就是——决心加上耐心!附录1:程序代码:#include #define Lcd_Data P0 //定义数据端口#define _TH0_TL0_ (65536 - 50000) #define HI (_TH0_TL0_ / 256) //给高8位赋值#define LO (_TH0_TL0_ % 256) //给低8位赋值#define M 20 //(1000/50)1秒要20个中断的累计 char hour = 0, min = 0, sec = 0,N=0,day=1,moth=1,week=7; //初始化要显示的值unsigned char SEG_TAB[] = {0x30,0x31,0x32, 0x33, 0x34, 0x35, 0x36, 0x37,0x38, 0x39};//0-9数字 unsigned int year=8;sbit RS = P2^ 5; //定义和LCD的连接端口sbit RW = P2^ 4;sbit E = P2^ 3;sbit Busy = P0^ 7;sbit S3 = P3^2;//定义开关s3选择键sbit S4 = P3^3;//s4加一键sbit S5 = P3^4;//s5减一键sbit DQ = P2^0;//DS18B20sbit speak = P2^1; //蜂鸣器警报/***************************************************************************/void delay1(unsigned int num)//短延时函数{ while( num-- );}/******************************************************************************/void Delay(unsigned char t)//长延时函数,延时 1MS*t S{ unsigned char a; while(--t != 0) { for(a = 0; a < 125; a++); }}/*******************************************************************/void Timer0Init(void) //初始化定时器0程序{ TMOD = 0x01; //设置模式1 定时器0 工作方式0 TH0 = HI; //给TH0,TL0赋初始值 TL0 = LO; TR0 = 1; //启动定时器0 ET0 = 1; //定时器中断开 EA = 1; //总中断开}/******************************************************************************/void Read_Busy(void)//读忙信号判断{ do{ Lcd_Data = 0xff; RS = 0; RW = 1; E = 0; Delay(2); E = 1; }while(Busy);}/******************************************************************************/ void Write_Comm(unsigned char lcdcomm) //写指令函数{ Lcd_Data = lcdcomm; RS = 0; RW = 0; E = 0; Read_Busy(); E = 1;}/******************************************************************************/void Write_Data(unsigned char lcddata)//写数据函数{ Lcd_Data = lcddata; RS = 1; RW = 0; E = 0; Read_Busy(); E = 1;}/******************************************************************************/void Init_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{ unsigned char x = 0; DQ = 1; //DQ复位 delay1(8); //稍做延时 DQ = 0; //单片机将DQ拉低 delay1(80); //精确延时 大于 480us DQ = 1; //拉高总线 delay1(14); x = DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay1(20);}/**********************************************************************************/ReadOneChar(void)//读一个字节{ unsigned char i = 0; unsigned char dat = 0; for (i = 8; i > 0; i--) { DQ = 0; // 给脉冲信号 dat >>= 1; DQ = 1; // 给脉冲信号 if(DQ) dat |= 0x80; delay1(4); } return (dat);}/**********************************************************************************/WriteOneChar(unsigned char dat)//写一个字节{ unsigned char i = 0; for (i。