1、单片机精确时钟报告1一摘要本作品使用STC89C52单片机作为控制核心,在学习板的基础上自行拓展了DS12C887时钟芯片以及1602液晶,蜂鸣器等器件,设计了一款具有多个功能的高精度时钟。该系统的设计与制作是一次在对单片机基本知识及基本应用掌握基础上的对单片机系统拓展设计的进一步尝试。二作品功能该作品基于SSt89C51单片机并利用液晶显示LCD1602以及DS12C887时钟芯片,通过程序控制实现了以下功能:1 1602液晶上显示年、月、日、星期、时、分、秒,并且按秒实时更新显示。2 具有闹铃设定及到时报警功能,报警响起时按任何键取消报警。3 能够使用板上的按键随时调节各个参数,4个有效键
2、,分别为功能选择键、数值增大键、数值减小键和闹钟查看键。三 工作原理本系统的工作原理是: 单片机通过对DS12C887时钟芯片内的时间信息进行采集,并将其显示于1602液晶上实现基本时间显示功能;单片机根据用户按键输入的信号通过程序控制实现时间更新功能及闹钟、报警功能。四硬件部分在学习板已有硬件模块基础上我们加入液晶显示模块、闹钟输出模块、时钟芯片等模块。此高精度时钟系统所包括的模块如图所示:1.时钟芯片 DS12C887能够自动产生世纪、年、月、日、时、分、秒等时间信息;对于一天内的时间记录,有12小时制和 24小时制两种模式。在 12小时制模式中,用 AM和 PM区分上午和下午;时间的表示
3、方法也有两种,一种用二进制数表示,一种是用 BCD码表示;DS12C887中带有 128字节 RAM,其中有 11字节 RAM用来存储时间信息,4字节 RAM用来存储DS12C887的控制信息,称为控制寄存器,113字节通用 RAM使用户使用;此外用户还可对 DS12C887进行编程以实现多种方波输出,并可对其内部的三路中断通过软件进行屏蔽。 2.液晶显示模块系统中采用LCD1602作为显示器件输出信息。与传统的LED数码管显示器件相比,液晶显示模块具有体积小、功耗低、显示内容丰富等优点,而且不需要外加驱动电路,现在液晶显示模块已经是单片机应用设计中最常用的显示器件了。LCD1602可以显示2
4、行16个字符,具有8位数据总线D0-D7,和RS、R/W、E三个控制端口,工作电压为5V,并且带有字符对比度调节和背光设置。3.键盘模块键盘在单片机系统中是一个很重要的部件。为了输入数据、查询和控制系统的工作状态,都要用到键盘。本实验用到键盘按键进行时间设置与调整作用 4.闹铃模块系统采用蜂鸣器作为闹铃输出。闹铃电路连接如图所示。软件设计本系统软件程序主要包括:液晶LCD1602的底层驱动模块、定时器0定时检查系统变量模块、定时器1按键扫描模块等。程序过程如图。主程序是先开始,然后初始化参数设置,定时器启动后在进行按键检测,显示时间。 1主程序MAIN流程框图 否 是 图6主程序MAIN流程框
5、图2定时器中断流程图程序开始进行标识位初始化,对时钟闹铃单元进行初始化,开始读取时间信息,通过读取程序,液晶显示器显示时间,当有按键按下时进行键值的处理,没有按键按下时则程序重新读取时间信息。定时器中断时是先检测1秒是否到,1秒如果到,秒单元就加1;如果没到,就检测1分钟是否到,1分钟如果到,分单元就加1;如果没到,就检测1小时是否到,1小时如果到,时单元就加1,如果没到,就显示时间。 图4-3 定时器中断流程图3时钟调整模式:4闹铃报时模式:结束语通过这次课程设计我发现,只有理论水平提高了;才能够将课本知识与实践相整合,理论知识服务于教学实践,以增强自己的动手能力。这个实验十分有意义 我获得
6、很深刻的经验。通过这次课程设计,我们知道了理论和实际的距离,也知道了理论和实际想结合的重要性,也从中得知了很多书本上无法得知的知识。我们的学习不但要立足于书本,以解决理论和实际教学中的实际问题为目的,还要以实践相结合,理论问题即实践课题,解决问题即课程研究,学生自己就是一个专家,通过自己的手来解决问题比用脑子解决问题更加深刻。学习就应该采取理论与实践结合的方式,理论的问题,也就是实践性的课题。这种做法既有助于完成理论知识的巩固,又有助于带动实践,解决实际问题,加强我们的动手能力和解决问题的能力。课程设计报告高 精 度 时 钟 设 计重庆邮电大学通信与信息工程学院周 礼(08010310)王一可
7、(08020301) 2010 年 5 月 30 日工作在一般时钟模式下:工作在闹钟模式下:【附录:源程序】#include #define uchar unsigned char #define uint unsigned intsbit dula=P10; /段选sbit wela=P11; /位选sbit rs=P35; /液晶数据/命令选择sbit lcden=P34; /液晶使能sbit s1=P00;/功能键sbit s2=P01;/增加键sbit s3=P02;/减小键sbit s4=P03;/闹钟查看键sbit oe=P13;sbit beep=P12;/蜂鸣器sbit dsc
8、s=P14;/ds时钟芯片片选sbit dsas=P15;/ds地址选通输入端sbit dsrw=P16;/ds读/写输入端sbit dsds=P17;/ds数据选择或读输入脚sbit dsirq=P33;/ds中断请求输出bit flag1,flag_ri;/定义两个位变量uchar count,s1num,flag,t0_num;/变量定义char miao,shi,fen,year,month,day,week,amiao,afen,ashi;uchar code table= 20 - - ;/液晶固定显示内容uchar code table1= : : ;void write_ds(
9、uchar,uchar);/函数申明void set_alarm(uchar,uchar,uchar);void read_alarm();uchar read_ds(uchar);void set_time();/-void delay(uint z)/延时函数 uint x,y; for(x=z;x0;x-) for(y=110;y0;y-);void di() /蜂鸣器报警声音 beep=0; delay(300); beep=1;void write_com(uchar com)/写液晶命令函数 rs=0; lcden=0; P2=0xff; P2=com; delay(3); lcd
10、en=1; delay(3); lcden=0; void write_date(uchar date)/写液晶数据函数 rs=1; lcden=0; P2=0xff; P2=date; delay(3); lcden=1; delay(3); lcden=0; void init()/初始化函数 uchar num; EA=1;/打开总中断 EX1=1;/开外部中断1 IT1=1;/设置负跳变沿触发中断 flag1=0;/变量初始化 dula=1; P0=0x00; dula=0;/关闭数码管显示 wela=1; P0=0xfe; wela=0; P0=0x00; t0_num=0; s1n
11、um=0; week=1; lcden=0; oe=0; write_com(0x38);/1602液晶初始化 write_com(0x0c); write_com(0x06); write_com(0x01); write_com(0x80); for(num=0;num15;num+)/写入液晶固定部分显示 write_date(tablenum); delay(1); write_com(0x80+0x40); for(num=0;num11;num+) write_date(table1num); delay(1); void write_sfm(uchar add,char date
12、)/1602液晶刷新时分秒函数4为时,7为分,10为秒 char shi,ge; shi=date/10; ge=date%10; write_com(0x80+0x40+add); write_date(0x30+shi); write_date(0x30+ge);void write_nyr(uchar add,char date)/1602液晶刷新年月日函数3为年,6为分,9为秒 char shi,ge; shi=date/10; ge=date%10; write_com(0x80+add); write_date(0x30+shi); write_date(0x30+ge);void
13、 write_week(char we)/写液晶星期显示函数 write_com(0x80+12); 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
14、 4: write_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);
15、 break; void keyscan() if(flag_ri=1) /这里用来取消闹钟报警,任一键取消报警 if(s1=0)|(s2=0)|(s3=0)|(s4=0) delay(5); if(s1=0)|(s2=0)|(s3=0)|(s4=0) while(!(s1&s2&s3&s4); di(); flag_ri=0;/清除报警标志 if(s1=0)/检测S1 delay(5); if(s1=0) s1num+;/记录按下次数 if(flag1=1) if(s1num=4) s1num=1; flag=1; while(!s1);di(); switch(s1num) /光标闪烁点定
16、位 case 1: write_com(0x80+0x40+10); write_com(0x0f); break; case 2: write_com(0x80+0x40+7); break; case 3: write_com(0x80+0x40+4); break; case 4: write_com(0x80+12); break; case 5: write_com(0x80+9); break; case 6: write_com(0x80+6); break; case 7: write_com(0x80+3); break; case 8: s1num=0; write_com
17、(0x0c); flag=0; write_ds(0,miao); write_ds(2,fen); write_ds(4,shi); write_ds(6,week); write_ds(7,day); write_ds(8,month); write_ds(9,year); break; if(s1num!=0)/只有当S1按下后,才检测S2和S3 if(s2=0) delay(1); if(s2=0) while(!s2);di(); switch(s1num) /根据功能键次数调节相应数值 case 1: miao+; if(miao=60) miao=0; write_sfm(10,
18、miao); write_com(0x80+0x40+10); break; case 2: fen+; if(fen=60) fen=0; write_sfm(7,fen); write_com(0x80+0x40+7); break; case 3: shi+; if(shi=24) shi=0; write_sfm(4,shi); write_com(0x80+0x40+4); break; case 4: week+; if(week=8) week=1; write_week(week); write_com(0x80+12); break; case 5: day+; if(day
19、=32) day=1; write_nyr(9,day); write_com(0x80+9); break; case 6: month+; if(month=13) month=1; write_nyr(6,month); write_com(0x80+6); break; case 7: year+; if(year=100) year=0; write_nyr(3,year); write_com(0x80+3); break; if(s3=0) delay(1); if(s3=0) while(!s3);di(); switch(s1num) /根据功能键次数调节相应数值 case
20、1: miao-; if(miao=-1) miao=59; write_sfm(10,miao); write_com(0x80+0x40+10); break; case 2: fen-; if(fen=-1) fen=59; write_sfm(7,fen); write_com(0x80+0x40+7); break; case 3: shi-; if(shi=-1) shi=23; write_sfm(4,shi); write_com(0x80+0x40+4); break; case 4: week-; if(week=0) week=7; write_week(week); w
21、rite_com(0x80+12); break; case 5: day-; if(day=0) day=31; write_nyr(9,day); write_com(0x80+9); break; case 6: month-; if(month=0) month=12; write_nyr(6,month); write_com(0x80+6); break; case 7: year-; if(year=-1) year=99; write_nyr(3,year); write_com(0x80+3); break; if(s4=0)/检测S4 delay(5); if(s4=0)
22、flag1=flag1; while(!s4);di(); if(flag1=0) /退出闹钟设置时保存数值 flag=0; write_com(0x80+0x40); write_date( ); write_date( ); write_com(0x0c); write_ds(1,miao); write_ds(3,fen); write_ds(5,shi); else /进入闹钟设置 read_alarm();/读取原始数据 miao=amiao;/重新赋值用以按键调节 fen=afen; shi=ashi; write_com(0x80+0x40); write_date(R);/显示
23、标志 write_date(i); write_com(0x80+0x40+3); write_sfm(4,ashi);/送液晶显示闹钟时间 write_sfm(7,afen); write_sfm(10,amiao); void write_ds(uchar add,uchar date)/写12C887函数 dscs=0; dsas=1; dsds=1; dsrw=1; P2=0xff; P2=add;/先写地址 dsas=0; dsrw=0; P2=0xff; P2=date;/再写数据 dsrw=1; dsas=1; dscs=1; uchar read_ds(uchar add)/读
24、12C887函数 uchar ds_date; dsas=1; dsds=1; dsrw=1; dscs=0; P2=0xff; P2=add;/先写地址 dsas=0; dsds=0; P2=0xff; ds_date=P2;/再读数据 dsds=1; dsas=1; dscs=1; return ds_date; void read_alarm()/读取12C887闹钟值 amiao=read_ds(1); afen=read_ds(3); ashi=read_ds(5);/-void main()/主函数 init();/调用初始化函数 while(1) if(flag_ri=1)/当闹
25、钟中断时进入这里 di(); delay(200); di(); delay(500); keyscan();/按键扫描 if(flag=0&flag1=0)/正常工作时进入这里 keyscan();/按键扫描 year=read_ds(9);/读取12C887数据 month=read_ds(8); day=read_ds(7); week=read_ds(6); shi=read_ds(4); fen=read_ds(2); miao=read_ds(0); write_sfm(10,miao);/送液晶显示 write_sfm(7,fen); write_sfm(4,shi); write_week(week); write_nyr(3,year); write_nyr(6,month); write_nyr(9,day); void exter() interru
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1