电子钟设计(毕业论文).docx
电子钟设计 摘 要本课程设计目的是设计一个可显示年、月、日、星期、时、分、秒的电子钟,并通过简易的按键操作方便的更改显示的时间。该电子钟控制电路由STC89C51单片机实现,时钟由DS1302时钟芯片提供,显示部分为1602液晶显示模块。本项目基本工作流程为:上电后单片机给DS1302时钟芯片写入一组初始时间,之后单片机定时向DS1302芯片读取时间信息,并通过1602液晶显示模块显示出来,当有控制按键按下后,单片机将更改的时间信号写入DS1302芯片,由于单片机不停的从DS1302芯片中读取信息显示在1602液晶显示模块上,从而实现时间的调整。通过反复调试和改进完全实现了预期要求。关键字:单片机 DS1302 液晶显示一、设计目的:设计一个可显示年、月、日、星期、时、分、秒的电子钟,并通过简易的按键操作方便的更改显示的时间。二、设计中的问题及分析:1)时钟信号的来源电子钟的时钟信号的来源一般有两种:单片机提供和时钟芯片提供。这两种时钟信号各有其利弊。采用单片机提供的方案电路结构简单,程序编写方便,但由于不同单片机工作的时钟频率不同程序的移植性不强,时钟的精度不高,一般还需占据单片机的一两个定时计数器,在系统设计时占用了宝贵资源。采用时钟芯片提供的方案虽然电路复杂一些但具有很高的时钟精度和程序的可移植性。通过比对本设计采用了时钟芯片DS1302来提供时钟信号。2)显示方式的选择显示方式也有两种方案:数码管显示和液晶显示,数码管虽有其价格低廉的优势但其功耗大电路复杂,显示稳定度差。出于功耗和显示质量的考虑在本设计中选用了1602液晶显示模块作为显示部分。3)按键的设计按键的作用是用于实现时间信号的更改,可行的方案有两种:数字键盘加功能键和只用功能键。数字键盘加功能键可以提供方便快捷的操作,但过多的按键数不适用本设计通过简易的按键操作方便的更改显示的时间的要求。最终本设计选择了只用功能键的设计方案,通过一个按键循环选择更改对象,通过另一个按键来循环增加时间值。三、硬件电路设计:1)电路如下所示:由于本人在开发板上完成该电子课程设计工作,电路图取自DY500开发板说明书。 图1 单片机电路 图2 DS1302时钟芯片电路 图3 1602液晶显示电路 图4 晶振、复位、按键电路2)芯片及模块说明1. DS1302时钟芯片DS1302慢速充电时钟芯片包括实时时钟/日历和31字节的静态RAM。它经过一个简单的串行接口与微处理器通信。实时时钟/日历提供秒、分、时、日、周、月和年等信息。对于小于31天的月,月末的日期自动进行调整,还包括了闰年校正的功能。时钟的运行可以采用24小时或带AM(上午)/PM(下午)的12小时格式。使用同步串行通信,简化了DS1302与微处理器的通信。与时钟/RAM通信仅需三根线:(1)RST (复位)、(2)I/O(数据线)、和(3)SCLK(串行时钟)。数据可以以每次一个字节或多达31字节的多字节形式传送至时钟/RAM或从其中送出。DS1302设计成能在非常低的功耗下工作,消耗小于1微瓦的功率便能保存数据和时钟信息。2. 1602液晶显示模块工业字符型液晶,能够同时显示16x02即32个字符。(16列2行)1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。四、使用方法及其显示结果 如图4所示,有两个按键S1和S2,其作用分别为:S1用于循环选择调整对象,如年份,日期等,被选择的对象所在位置光标闪烁用于指示位置。S2键用于循环增加被S1选中的信息,单片机控制被选信息的循环规律,如调整“月”的个位,当月的十位为零时,个位增加到9后才归零,而当十位为一时,个位增加到2后就归零,这样显示器上不会显示与现实不符合的时间。当时间调整时时钟会停止,直至一次调整完成才恢复运行。该时钟复位时间为2000-00-00 DAY00:00:00,依次为年、月、日、星期、时、分、秒,其中DAY表示星期通过调整可显示星期的英文缩写MON、TUE、WED、THU、FRI、SAT、SUN。液晶显示器右下角显示的“铃”形标志是本人用于在本电子钟上附加闹铃功能而设计的,但因闹铃功能设计尚未完成,故不能完成该部分工作。 图5 单片机开发板 图6 上电5S时 图7 调整年的各个位 图8 调整星期由图7和图8可以看到被调整的时间项的所在位置光标闪烁,并且时钟停止(两图时间显示都为“00:00:43”)。图9 调整的当前时间 图10 运行8分钟之后由上所列图片,可以看到本设计能完全大道设计要求。五程序 /*电子钟设计,显示年、月、日、星期、时、分、秒 设计时间2009-12-29 */#include<reg52.h>/完成显示和变化值显示#define uint unsigned int#define uchar unsigned charuchar data time8=0;uchar data time18=0;uchar code t=0x04,0x0e,0x0e,0x1f,0x1f,0x00,0x04,0;/闹铃的代码uchar code day="DAY MON TUE WED THU FRI SAT SUN"uchar key,n,n1;sbit SCK=P35;sbit SDA=P36;sbit RST = P37; / DS1302复位sbit rs=P22;sbit en=P24;sbit rw=P23;sbit k1=P30;sbit k2=P31;sbit k3=P33;void delay(uchar c) /延时 uchar a,b; for(a=0;a<c;a+) for(b=0;b<110;b+) ;void write1(uchar temp) /写 uchar i; for (i=0;i<8;i+) /循环8次 写入数据 SCK=0; SDA=temp&0x01; /每次传输低字节 temp>>=1; /右移一位 SCK=1; void write(uchar address,uchar dat ) /写一位 RST=0; SCK=0; RST=1; /启动 write1(address);/发送地址 write1(dat);/发送数据 RST=0; /恢复void write_n() /写日历8位 uchar m; RST=0; SCK=0; RST=1; write1(0xbe); for(m=0;m<8;m+) write1(timem); RST=0; uchar read1() /读 uchar i,tem; for (i=0;i<8;i+) /循环8次 读取数据 tem>>=1;/每次传输低字节SCK=0; if(SDA) tem|=0x80; /右移一位 SCK=1; return(tem);uchar read( uchar address ) /读一位 uchar temp=0x00; RST=0; SCK=0; RST=1; write1(address); temp=read1(); RST=0;/以下为DS1302复位的稳定时间SCK=0;SDA=1;return (temp);/返回void read_n() /读日历8位 uchar m;/liya_10 RST=0; SCK=0; RST=1; write1(0xbf); for(m=0;m<8;m+) timem=read1(); RST=0;SCK=0;SDA=1; void dsdate() /运算 uchar m; for(m=0;m<8;m+) time1m=timem>>4; for(m=0;m<8;m+) timem&=0x0f; void delay1(uchar c) /延时 uint a,b; for(a=0;a<c;a+) for(b=0;b<11;b+) ;void write_add(uchar add) /1602写指令 en=0; rs=0; rw=0; P0=add; en=1; en=0; P0=0xff; void write_date(uchar date)/1602写数据 en=0; rs=1; rw=0; P0=date; en=1; en=0; P0=0xff; void chu() /1602初始化 write_add(0x01); delay1(1); write_add(0x38); delay1(1); write_add(0x0c); delay1(1); write_add(0x06); delay1(1);void key2(uchar m) uchar t; if(k2=0) delay(10); while(k2=0); timem+; if(timem=n) timem=0; time1m<<=4; t=timem+time1m; if(t>=n1) t=0; m<<=1; m+=0x80; write(m,t); void key3(uchar m) uchar t; if(k2=0) delay(10); while(k2=0); time1m+; if(time1m=n) time1m=0; time1m<<=4; t=timem+time1m; if(t>=n1) t=0; m<<=1; m+=0x80; write(m,t); void key1() /按键 uchar mao; if(k1=0) delay(10); while(k1=0); key+; if(key!=0) mao=read(0x81); mao|=0x80; write(0x80,mao); delay1(1); if(key=1) write_add(0x83);n=10;n1=0xa0;key3(6); if(key=2) write_add(0x84);n=10;n1=0xa0;key2(6); if(key=3) write_add(0x86);n=2;n1=0x13;key3(4); if(key=4) write_add(0x87);n=10;n1=0x13;key2(4); if(key=5) write_add(0x89);n=4;n1=0x32;key3(3); if(key=6) write_add(0x8a);n=10;n1=0x32;key2(3); if(key=7) write_add(0x8d);n=8;n1=8;key2(5); if(key=8) write_add(0xc2);n=3;n1=0x24;key3(2); if(key=9) write_add(0xc3);n=10;n1=0x24;key2(2); if(key=10) write_add(0xc5);n=6;n1=0x60;key3(1); if(key=11) write_add(0xc6);n=10;n1=0x60;key2(1); if(key=12) key=0; delay1(1); write_add(0x0F); delay1(1); delay(60); write_add(0x0c); mao&=0x7f; write(0x80,mao); void tu() uchar m; write_add(0x40);/自定义区入口地址 for(m=0;m<8;m+)/写代码 delay1(1); write_date(tm); void main() uchar k,d; key=0; write_n();/ mao=read(0x81);/ mao|=0x80;/write(0x80,0); chu(); tu(); delay1(2); while(1) read_n(); dsdate(); write_add(0x81); /显示年 delay1(1); write_date('2'); delay1(1); write_date('0'); delay1(1); write_date(time16+0x30); delay1(1); write_date(time6+0x30); delay1(1); write_date('-'); for(k=5;k>3;k-) /显示年月日 delay1(1); write_date(time1k-1+0x30); delay1(1); write_date(timek-1+0x30); delay1(1); if(k=4) break; write_date('-'); delay1(1); write_add(0x8d); /显示星期 delay1(1); d=time5<<2; for(k=0;k<3;k+) write_date(dayd+k); delay1(1); write_add(0x82+0x40); delay1(1); for(k=3;k>0;k-) /显示时间 delay1(1); time1k-1&=0x07; write_date(time1k-1+0x30); delay1(1); write_date(timek-1+0x30); delay1(1); if(k=1) break; write_date(':'); delay1(1); write_add(0x8d+0x40); delay1(1); write_date(0); key1();