1、电子设计大赛作品51单片机的实时时钟制作之欧阳化创编时间:2021.02.06创作:欧阳化河北大学工商学院 电子设计竞赛报告题目:使用DS12C887时钟芯片设计高精度时钟学 部 信息科学与工程学部专 业 电气一类学 号 2009480102姓 名 田海茂2011年3月12日 一 摘要 3二 系统组成与功能说明 3三 硬件电路设计与分析 2四 程序流程说明 3附录1 .摘要本系统利用单片机(STC89C52)和DS12C887时钟芯片实现对时间的控制。在1602液晶上显示年,月,日,星期,时,分,秒,并且按秒实时更新显示;具有闹铃报警功能;具有更改功能,能任意更改时间;利用DS12C887自身
2、掉电可继续走时的特性,实现断电时间不停,再次上电时时间仍准确显示在液晶上的功能。以上各种功能依据一定的联系,组成一个比较完整的系统。一 系统组成与功能说明系统可划分为几个功能模块,如图1所示。 图1通过STC89C52单片机按键的扫描函数实现对更改时间功能的控制。在外部断电情况下DS12C887仍能继续走时,再次上电时将准确时间传给单片机,从而实现时间不停的功能,当闹钟时间到时,DS12C887发出中断申请,单片机控制液晶停止走时,通过蜂鸣器发出闹铃声,并且按键与蜂鸣器相连,按下按键的同时蜂鸣器会发出响声。采用个性化的液晶显示,当开始供电时以屏幕的平移为起始,时间信息从右往左平移至中央。二 硬
3、件电路设计与分析硬件电路原理图如下所示最小系统图1602液晶与单片机连接图DS12C887与单片机连接图以STC89C52为核心制作出单片机最小系统。1602液晶为5V电压驱动,带背光,可显示两行,每行16个字符,符合本作品需要。DS12C887具有闹铃以及外部掉电自身继续走时功能,为理想的时钟芯片。选择蜂鸣器,通过用三极管对其放大,实现所想要的功能。选择RS232,使得计算机的9.6V的电压能够与该系统5V得以匹配,与此同时也实现了我们直接用电脑直接对其系统直接拷贝程序。三 程序流程说明 图 主程序流程图附件1#include#define uchar unsigned char #defi
4、ne uint unsigned intsbit rs=P35;sbit lcden=P34;sbit s1=P36;/功能键sbit s2=P31;/增大键sbit s3=P32;/减小键sbit beep=P23;/蜂鸣器sbit dscs=P14;sbit dsas=P15;sbit dsrw=P16;sbit dsds=P17;sbit dsirq=P33;uchar count,s1num,flag;bit flag1;char miao,shi,fen,nian,yue,ri,week;uchar code table= 20 - - ;/液晶固定显示uchar code tabl
5、e1= : : ;uchar code table2= Hello everyone!;uchar code table3=Nice to meet you!;void write_ds(uchar,uchar);void set_alarm(uchar,uchar,uchar);uchar read_ds(uchar);void set_time();uchar amiao,ashi,afen;void delay(uint z)/延时函数 uint x,y; for(x=z;x0;x-) for(y=110;y0;y-);void di()/按键时蜂鸣器发音 beep=0; delay(1
6、00); beep=1;void didi() /闹钟时蜂鸣器发音 beep=0; delay(50); beep=1; delay(100); beep=0; delay(50); beep=1;void write_com(uchar com)/写液晶命令函数 rs=0; lcden=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; void write_date(uchar date)/写液晶具体数据函数 rs=1; lcden=0; P0=date; delay(5); lcden=1; delay(5); lcden=0; void i
7、nit()/程序初始化 uchar num; EA=1;/打开总中断 EX1=1;/开外部中断1 IT1=1;/设置负跳变沿触发方式 lcden=0; week=1;/ set_time();/给DS12C887设置时间函数 set_alarm(2,2,10);/设置闹铃函数 write_ds(0x0B,0x26);/设置DS12C887 24小时模式 write_com(0x38);/1602液晶初始化 write_com(0x0c); write_com(0x06); write_com(0x01); write_com(0x80); for(num=0;num16;num+)/写入液晶平
8、移内容 write_date(table2num); delay(5); write_com(0x80+0x40); for(num=0;num16;num+) write_date(table3num); delay(5); write_com(0x80+0x10);/写入液晶固定内容 for(num=0;num16;num+) write_date(tablenum); delay(5); write_com(0x80+0x50); for(num=0;num16;num+) write_date(table1num); delay(5); void write_sfm(uchar add
9、,uchar date)/在液晶上写入时分秒 uchar shi,ge; shi=date/10; ge=date%10; write_com(0x80+0x50+add); write_date(0x30+shi); write_date(0x30+ge);void write_sfm1(uchar add,uchar date)/在液晶上写入年月日 uchar shi,ge; shi=date/10; ge=date%10; write_com(0x80+0x10+add); write_date(0x30+shi); write_date(0x30+ge);void write_week
10、(uchar we)/星期函数 write_com(0x80+0x10+13); switch(we) case 1: write_date(M);delay(5); write_date(O);delay(5); write_date(N); break; case 2: write_date(T);delay(5); write_date(U);delay(5); write_date(E); break; case 3: write_date(W);delay(5); write_date(E);delay(5); write_date(D); break; case 4: write_
11、date(T);delay(5); write_date(H);delay(5); write_date(U); break; case 5: write_date(F);delay(5); write_date(R);delay(5); write_date(I); break; case 6: write_date(S);delay(5); write_date(A);delay(5); write_date(T); break; case 7: write_date(S);delay(5); write_date(U);delay(5); write_date(N); break; vo
12、id keyscan() if(flag1=1)/闹铃响 if(s2=0) delay(5); if(s2=0) while(!s2);di(); flag1=0;/中断闹铃 if(s3=0) delay(5); if(s3=0) while(!s3); di(); flag1=0;/中断闹铃 if(s1=0) delay(5); if(s1=0) s1num+; flag=1; flag1=0; while(!s1);di(); if(s1num=1) write_com(0x80+0x50+10); write_com(0x0f);/光标停止位置不断闪烁 if(s1num=2) write
13、_com(0x80+0x50+7); if(s1num=3) write_com(0x80+0x50+4); if(s1num=4) write_com(0x80+0x10+13); if(s1num=5) write_com(0x80+0x10+10); if(s1num=6) write_com(0x80+0x10+7); if(s1num=7) write_com(0x80+0x10+4); if(s1num=8) s1num=0; write_com(0x0c);/光标停止闪烁 write_ds(0,miao);/将此时时间信息写入DS12C887 write_ds(2,fen); w
14、rite_ds(4,shi); write_ds(6,week); write_ds(7,ri); write_ds(8,yue); write_ds(9,nian); flag=0; if(s1num!=0) if(s2=0) delay(1); if(s2=0) while(!s2); di(); if(s1num=1) miao+; if(miao=60) miao=0; write_sfm(10,miao);/将变化后的时间写入液晶 write_com(0x80+0x50+10); if(s1num=2) fen+; if(fen=60) fen=0; write_sfm(7,fen)
15、; write_com(0x80+0x50+7); if(s1num=3) shi+; if(shi=24) shi=0; write_sfm(4,shi); write_com(0x80+0x50+4); if(s1num=4) week+; if(week=8) week=1; write_week(week); write_com(0x80+0x10+13); if(s1num=5) ri+; if(ri=32) ri=1; write_sfm1(10,ri); write_com(0x80+0x10+10); if(s1num=6) yue+; if(yue=13) yue=1; wr
16、ite_sfm1(7,yue); write_com(0x80+0x10+7); if(s1num=7) nian+; if(nian=100) nian=0; write_sfm1(4,nian); write_com(0x80+0x10+4); if(s3=0) delay(1); if(s3=0) while(!s3); di(); if(s1num=1) miao-; if(miao=-1) miao=59; write_sfm(10,miao); write_com(0x80+0x50+10); if(s1num=2) fen-; if(fen=-1) fen=59; write_s
17、fm(7,fen); write_com(0x80+0x50+7); if(s1num=3) shi-; if(shi=-1) shi=23; write_sfm(4,shi); write_com(0x80+0x50+4); if(s1num=4) week-; if(week=0) week=7; write_week(week); write_com(0x80+0x10+13); if(s1num=5) ri-; if(ri=0) ri=31; write_sfm1(10,ri); write_com(0x80+0x10+10); if(s1num=6) yue-; if(yue=0)
18、yue=12; write_sfm1(7,yue); write_com(0x80+0x10+7); if(s1num=7) nian-; if(nian=-1) yue=99; write_sfm1(4,nian); write_com(0x80+0x10+4); void write_ds(uchar add,uchar date)/ DS12C887写入程序函数 dscs=0; dsas=1; dsds=1; dsrw=1; P0=add; dsas=0; dsrw=0; P0=date; dsrw=1; dsas=1; dscs=1; uchar read_ds(uchar add)/
19、从DS12C887中读取数据 uchar ds_date; dsas=1; dsds=1; dsrw=1; dscs=0; P0=add; dsas=0; dsds=0; P0=0xff; ds_date=P0; dsds=1; dsas=1; dscs=1; return ds_date; void set_time()/设置时间 write_ds(4,1); write_ds(2,2); write_ds(6,3); write_ds(7,4); write_ds(8,5); write_ds(9,6);void set_alarm(uchar ashi,uchar afen,uchar
20、amiao)/设置闹铃 write_ds(1,amiao); write_ds(3,afen); write_ds(5,ashi);void main() uchar num,bo=0; init(); delay(4000); for(num=0;num16;num+) write_com(0x18);/1602平移函数 delay(600); keyscan();/按键检测 if(flag1=1) didi(); if(flag=0) miao=read_ds(0);/平移时从时钟芯片中读取时间 fen=read_ds(2); shi=read_ds(4); week=read_ds(6)
21、; ri=read_ds(7); yue=read_ds(8); nian=read_ds(9); write_sfm(10,miao);/平移时将读取的时间写到液晶 write_sfm(7,fen); write_sfm(4,shi); write_week(week); write_sfm1(10,ri); write_sfm1(7,yue); write_sfm1(4,nian); while(1) keyscan(); if(flag1=1) didi(); if(flag=0) miao=read_ds(0);/读取数据 fen=read_ds(2); shi=read_ds(4); week=read_ds(6); ri=read_ds(7); yue=read_ds(8); nian=read_ds(9); write_sfm(10,miao);/写入数据 write_sfm(7,fen); write_sfm(4,shi); write_week(week); write_sfm1(10,ri); write_sfm1(7,yue); write_sfm1(4,nian); void exter() interrupt 2 uchar c; flag1=1; c=read_ds(0x0c);时间:2021.02.06创作:欧阳化