毕业设计基于51单片机的万年历设计1.docx

上传人:scccc 文档编号:13196117 上传时间:2021-12-18 格式:DOCX 页数:30 大小:246.45KB
返回 下载 相关 举报
毕业设计基于51单片机的万年历设计1.docx_第1页
第1页 / 共30页
毕业设计基于51单片机的万年历设计1.docx_第2页
第2页 / 共30页
毕业设计基于51单片机的万年历设计1.docx_第3页
第3页 / 共30页
毕业设计基于51单片机的万年历设计1.docx_第4页
第4页 / 共30页
毕业设计基于51单片机的万年历设计1.docx_第5页
第5页 / 共30页
点击查看更多>>
资源描述

《毕业设计基于51单片机的万年历设计1.docx》由会员分享,可在线阅读,更多相关《毕业设计基于51单片机的万年历设计1.docx(30页珍藏版)》请在三一文库上搜索。

1、基于 51 单片机的万年历设计单片机经过几十年的发展, 已经广泛应用于生活中的各个领域。 单片机以其体 积小、功能全、性价比高等诸多优点,在许多行业都得到了广泛应用。在工业控 制、家用电器、通信设备、信息处理、尖端武器等各种测控领域的应用中独占鳌 头,单片机开发技术已成为电子信息、电气、通信、自动化、机电一体化等专业 技术人员必须掌握的技术。基于单片机的万年历作为设计的课题, 因为它有很好的开放性和可发挥性, 对 作者的要求比较高,不仅考察了对单片机的掌握能力而且强调了对单片机扩展的 应用。另外液晶显示的万年历已经越来越流行,特别适合在家庭居室、办公室、 大厅、会议室、车站和广场等地方使用,它

2、具有显示清晰直观、走时准确、可以 进行夜视等功能,并且还可以扩展出其它多种功能。所以,电子万年历作为设计 课题很有价值。现在对于电子万年历的设计大多运用 51 单片机。主要是因为 51 单片机种类齐 全、结构体系完整、指令系统功能完善、性能优越、具有较高可靠性和高性价比 等特点。本篇论文主要介绍了运用单片机实现电子万年历的设计 , 万年历系统拟用STC89C5单片机控制,以DS1302时钟芯片计时、1602液晶屏显示。系统主要由单片机控制电路,显示电路以及校正电路三个模块组成。本文阐述了系统的硬件 工作原理,所应用的各个接口模块的功能以及其工作过程,论证了设计方案理论 的可行性。目录第一章 绪

3、论 11.1 本课题主要的研究工作 1第二章 系统的硬件设计与实现 22.1 电路设计框图 22.2 系统硬件概述 22.3 主要单元电路的设计 22.3.1 单片机主控制模块的设计 22.3.2 时钟电路模块的设计 32.3.3 独立式键盘设计 42.3.4 显示模块的设计 4第三章 系统的软件设计 63.1 程序流程图 . 63.1.1 系统总流程图 63.1.2 DS1302 时钟程序流程图 73.1.3 LCD 显示程序流程图 83.2 程序的设计 93.2.1 DS1302 读写程序 93.2.2 液晶显示程序 11第四章 仿真与调试 134.1 KEIL 软件调试流程 . 134.

4、2 PRoteu软件运行流程 134.3 万年历的功能仿真 13致 谢 15参考文献 16附录:主程序 17第一章 绪论1.1 本课题主要的研究工作本项目是一种基于 AT89C51片机的万年历设计,本方案以AT89C51片机作为 主控核心,与时钟芯片DS1302、按键、LCD1602液晶显示器组成硬件系统。在硬 件系统中设有独立按键和 LCD1602 显示器,能显示丰富的信息,根据使用者的需 要可以随时对时间进行更改,读取方便、显示直观。当程序执行后,LCD显示即时时间、年月日、星期。设置 4个操作键:K1:选 择键;K2:加键;K3:减键;K4:确定键。1 本设计的主要内容:(1)熟悉万年历

5、各模块的工作原理;(2)选择适当的芯片和元器件,确定系统电路,绘制电路原理图,尤其 是各接口电路;(3)熟悉单片机使用方法和 C语言,编写出相应模块的应用程序;(4)分别在各自的模块中调试出对应的功能,在 Proteus 软件上进行仿 真,并实现各种功能。2 设计目标:万年历实现以下三个功能:(1)具有年、月、日、星期、时、分、秒等功能;(2)具备年、月、日、星期、时、分、秒校准功能,具备自动调节闰年 的功能;(3)具有与即时时间同步的功能。28第二章系统的硬件设计与实现2.1电路设计框图根据设计方案给出了系统总体的设计框图,如图1所示:LCD液晶模块DS1302模块主控制殮块TS键盘模块图1

6、为使时钟走时与标准时间一致,校时电路是必不可少的,键盘模块用来校正 液晶上显示的时间;STC89C51单片机通过输出各种电脉冲信号来驱动控制各部分 正常工作;而系统的时间、等数据则最终通过液晶模块显示出来。2.2系统硬件概述本电路是以STC89C5单片机为控制核心,该芯片具有在线编程功能,功耗低, 能在3.3V的超低压下工作;时钟芯片采用DS1302它是一款高性能、低功耗、自带RAM勺实时时钟芯片, 具有掉电自动保存功能。可自动对秒、分、时、日、周、月、年进行计数,具有 闰年补偿功能,而且精度高位的 RAM做为数据暂存区,工作电压2.5V5.5V范围 内,2.5V时耗电小于300nA。显示模块

7、采用1602显示屏,它内置192种字符,可显示32个符号或数字,清 晰可见,而且功率消耗小寿命长抗干扰能力强。其工作电压为5v。2.3主要单元电路的设计2.3.1单片机主控制模块的设计一个典型的单片机最小系统一般由时钟电路、复位电路、电源指示灯和外部 扩展接口等部分组成。单片机的最小系统如下图所示,单片机的XTAL0和XTAL1引脚用于连接晶振电 路。RESET为复位引脚,连接复位电路,用于初始化MCU232时钟电路模块的设计DS1302内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口 与单片机进行通信。图中VCC伪后备电源,VCC2为主电源。DS1302由VCC1或VCC2 两

8、者中的较大者供电。所以在主电源关闭的情况下,也能保持时钟的连续运行。X1和X2是振荡源,外接32.768KHZ晶振用来为芯片提供计时脉冲。RST是复位/ 片选线,通过把RST俞入驱动置高电平来启动所有的数据传送。DS1302的硬件接线图如图2所示:C2Header 2图2时钟芯片DS1302的工作原理:(1) DS1302的控制字节:DS1302控制字节的高有效位(位7)必须是逻辑1, 如果它为0,贝U不能把数据写入 DS1302中,位6如果为0,则表示存取日历时钟 数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位 0)如为0表示要进行写操作,为1表示进行读操作,控制

9、字节总是从最低位开始 输出(2) 数据输入输出(I/O ):在控制指令字输入后的下一个 SCLK寸钟的上升沿 时,数据被写入DS1302数据输入从低位即位0开始。同样,在紧跟8位的控制 指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位 0 位到高位7。(3) DS1302的寄存器:DS1302有 12个寄存器,其中有7个寄存器与日历、 时钟相关,存放的数据位为BCD码形式。“ CH是时钟暂停标志位,当该位为1时, 时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。“WP 是写保护位,在任何的对时钟和 RAM的写操作之前,“WP必须为0。当“WP

10、为 1 时,写保护位防止对任一寄存器的写操作。2.3.3 独立式键盘设计独立式键盘每个键单独占用一根 I/O 口线。键盘的工作方式可分为编程控制 方式和中断控制方式。CPU在 一个工作周期内,利用完成其他任务的空余时间,调 用键盘扫描子程序,经程序查询,若无键操作,则返回;若有键操作,则进而判 断是哪个键,并执行相应的键处理程序。这种方式为编程扫描方式。由于单片机 在正常应用过程中,可能会经常进行键操作,因而编程控制方式使CPU经常处于工作状态, 在进行本次设计中,只涉及到了选择、加、减、确定四个功能。因此 采用独立式键盘。2.3.4 显示模块的设计本设计中要对时间、温度进行显示,液晶显示屏

11、1602模块作为输出。 1602字 符型LCD!常有14条引脚线或16条引脚线的LCD多出来的2条线是背光电源线。 它可以显示两行,每行16个字符,采用单+5V电源供电,外围电路配置简单。1602 液晶模块内部的字符发生存储器已经存储了 160 个不同的点阵字符图形,每一个 字符都有一个固定的代码,比如大写的英文字母“ A”的代码是01000001B(41H), 显示时模块把地址 41H中的点阵字符图形显示出来,我们就能看到字母“A”。LCD1602引脚功能:1 VSS般接地2 VDD接 电源(+5V)3 V0 液晶显示器对比度调整端。4 RS RS为寄存器选择。5 R/WR/W为读写信号线。

12、6 E E(或EN)端为使能(enable)端,下降沿使能。1602主要管脚介绍:V0为液晶显示器对比度调整端,接正电源时对比度最弱, 接地电源时对比度最高,对比度过高时会产生鬼影使用时可以通过一个 10K 的电 位器调整对比度。RS为寄存器选择端,高电平时选择数据寄存器,低电平时选择指令寄存器。R/W为读写信号线端,高电平时进行读操作,低电平时进行写操作。 当RS和R/W共同为低电平时可以写入指令或者显示地址;当RS为高电平R/W为低电平时可以写入数据。E为使能端,当E端由高电平跳变成低电平时,液晶模块 执行命令。将L1602的RS端和P2.0,R/W端和P2.1, E 端和P2.2相连,当

13、RS=0 时,对LCD1602写入指令;当RS=1时,对LCD1602写入数据。当R/W端接高电平 时芯片处于读数据状态,反之处于写数据状态,E端为使能信号端。当R/W为高电 平,E端也为咼电平,RS为低电平时,液晶显示屏显示需要显示的示数。显示模块电 路图如图3所示:VCCU1101112J1115 -i6上i7:18 i1920P1.0(T2) P1.1(T2EX) P1.2P1.3P1.4P1.5P1.6 P1.7 RESET (RXD)P3.0 (TXD)P3.1 P3.2(INT0) P3.3(INT1) P3.4(T0) P3.5(T1)P3.6(WR) P3.7(RD XTAL0

14、 XTAL1VSSVCCT10K3产4540I6VCCP0.0P0.1P0.2P0.3P0.4P0.5P0.6P0.7 ea/VppALE/PROGPSENP2.7P2.6P2.5P2.4P2.3P2.2P2.1P2.039W373635262423222178910111213141516VSS VDD V0 RS RW EDB0DB1DB2DB3DB4DB5DB6DB7E1E2LCD1602VCCST8C9C52第三章系统的软件设计3.1程序流程图3.1.1系统总流程图系统总流程图分析:首先系统初始化,系统开始运行,当有设置键按下时进 入修改时间模式,无按键按下时读取时间、温度等数据送入液

15、晶屏显示;在修改 时间模式下设置时间完成后再送数据到液晶屏显示,如图 4所示:图43.1.2 DS1302时钟程序流程图入液晶屏显示。这时若有设置键按下时,进行时间修改,完成后将数据送入 时钟芯片;若没有按键按下,则直接存入EPROM送入液晶屏显示。时钟程序S1302 开始计时时,首先进行初始化,当有中断信号时,读取时钟芯片的数据,如图5所示:图53.1.3 LCD显示程序流程图显示程序流程图分析:首先对1602显示屏进行初始化(初始化大约持续10ms号,左右),然后检查忙信号,若BF=O,则获得显示RAM的地址,写入相应的数据显示;若BF=1,则代表模块正在进行内部操作,不接受任何外部指令和

16、数据,直到BF=O为止,如图6所示:J结束3.2程序的设计321 DS1302读写程序DS1302是 SPI总线驱动方式。它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。要想与 DS1302通信,首先要先了解 DS1302的控制字。DS1302的控制字如图7:765432101RAMA4A3UKA2AlAORD控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK寸钟的上升沿时,数据被写入 DS1302数据输入从最低位(0位)开始。同样,在紧跟 8 位的控制字指令后的下一个 SCLK脉冲的下降沿,读出DS1302的数据,读出的 数据也是从最低位到最高位。依据读写时序如图8和图9

17、:一(尺帀 1畑 z 1盟 i 盟 |阳 |眈”-图8单字节读RST龊lk丄fLfmfLfunLrLfLfLfLfLTLfnLfnjn 0( R/讦 肌 刚 A2 | 阳 | 第1Di D2 D3 D4 D5 D6 3图9 单字节写在进行任何数据传输时,RST必须被置高电平,每个SCLK为上升沿时数据被 输入,下降沿时数据被输出。先把 RST置低,禁止数据传输,SCLK置低,清零时 钟总线,RST再置高,允许数据传输。传送完成后,RST置低,禁止字节的传送。部分源程序如下:void write_byte(uchar dat) /写一个字节ACC=dat;RST=1;for(a=8;a>0

18、;a-) IO=ACC0;SCLK=0;SCLK=1;ACC=ACC>>1;uchar read_byte() / 读一个字节RST=1;for(a=8;a>0;a-)ACC7=IO;SCLK=1;SCLK=0;ACC=ACC>>1;return (ACC);void write_1302(uchar add,uchar dat) /向 1302 芯片写函数,指定写入地址,数据RST=0;SCLK=0;RST=1;write_byte(add);write_byte(dat);SCLK=1;RST=0;uchar read_1302(uchar add) / 从

19、1302 读数据函数,指定读取数据来源 地址uchar temp;RST=0;SCLK=0;RST=1;write_byte(add);temp=read_byte();SCLK=1;RST=0;return(temp);3.2.2 液晶显示程序1602通过D0D7的8位数据端传输数据和指令,其模块内的控制器有11条控 制指令。当液晶显示屏的接口电路与单片机系统 I/O 按照并行数据传输方式连接 完成以后,即可以对STC89C5单片机进行编程。在液晶屏完成显示之前首先要对 液晶进行初始化。部分源程序如下:lcdnit()/*液晶初始化函数*write_1602com(0x38); /设置液晶工

20、作模式, 16*2行显示, 5*7点阵, 8位数据 write_1602com(0x0c);/开显示不显示光标write_1602com(0x06);/整屏不移动,光标自动右移write_1602com(0x01);/清显示write_1602com(yh+1); /日历显示固定符号从第一行第 1 个位置之后开始显示 for(a=0;a<14;a+)write_1602dat(tab1a); /向液晶屏写日历显示的固定符号部分 /delay(3);write_1602com(er+2); /时间显示固定符号写入位置, 从第 2 个位置后开始显示 for(a=0;a<8;a+)wri

21、te_1602dat(tab2a); /写显示时间固定符号,两个冒号delay(3);第四章 仿真与调试4.1 Keil 软件调试流程建立新工程并保存,保存后会弹出一个设备选择对话框,选择MCU后点确定返回主界面。新建文件并保存,以 .C 为后缀。接着选择 Source Group1 ,右击鼠 标弹出快捷菜单,选择“ Add File to Group 'Source Groupl ",出现一个对话 框,加入文件后点 close 返回主界面。再打开工程属性设置对话框,主要设置工 作包括在Target选项卡中设置晶振频率、在Debug选项卡中设置生成hex文件等。 然后编写程序

22、并调试。在模拟调试程序后,还须通过编程器将 .hex 目标文件写入 单片机中才能观察仿真的效果。4.2 Proteus 软件运行流程运行Proteus程序后,进入软件的主界面,过左侧工具栏中的P(从库中选择元件命令 )命令,在 Pick Devices 左侧窗口中选择所需元件的关键字,然后放置 元件并调整方向和位置以及参数设置,最后进行连线。按 P 在库中查找元器件, 将所需要的元器件放置好后,绘制成原理图。4.3 万年历的功能仿真当电路搭建好之后,选中单片机 STC89C5,1 左键点击 STC89C5,1 在出现的对 话框里点击Program File按钮,找到刚才Keil软件编译得到的H

23、EX文件,载入 然后点击“0K按钮就可以模拟了。点击模拟调试按钮的运行按钮,进人调试状 态。按相应的按键可调节分,时,星期,日期,月份,年份,并且可以自动闰年 调整。按键功能自上而下依次为:选择键、加、减、确定。在 Protues 中仿真, 如图 10,图 11,图 12所示: 1LCD +RTE l0-L2-2?riONTIFE lSi 2H 46:.: I AlC2 :=rr°:RF1 -1-, 总口 :VO %LK TOTWC2X1U2 DS133Z胡iH<7z- S'v4JTT il 1KTAjinKTKI2BSTPCL1M1 阳別畑 PgWPOL 4/04 卩

24、口敬修PEUkbSPH T/H iiTPSENPZ1TASP2.1M9 PZ2AC P ZA11AL£FZ.AH0P1 0PZAG PZJffAU 工T慣皆FlUKXbPl 1/T: pjiwinP1.1 PUM3 P-| 4,psaTim勺 mTOP-15P -I AFgjrriR1.T1S 3n qj 广 o .-sr3"空衿/ Z ITW.?23 B 7w叫二.1.至di T31 n?-T3#OS 匚卫 d3Z orilDT N fl 3« - 4 I d3 612nSISTKI博毎腑囲庁申弗鼠:喜月日厅分):- IBej_zL-口O-0o o , oja.

25、10'AHIB *M3,"HTTT图10电路图仮复按"Fki选择所调节的时象(年月目时分):.搖咼d dm .o ao o图11键盘调节图12调节键盘后致谢至此,关于毕业设计的所有内容就介绍完了,系统的仿真电路和程序设计合 理。在整个设计过程中,充分发挥了人的主观能动性,自主学习,学到了许多没 学到的知识。程序编写中,由于思路不清晰,开始时遇到了很多的问题,经过静 下心来思考查资料,和同学讨论,理清了思路,完成对程序的编写。通过设计提 高了对单片机的认识,进一步熟悉和掌握单片机的结构及工作原理。通过实际程 序设计和调试,逐步掌握模块化程序设计方法和调试技术,提高软件

26、设计、调试 能力;通过这次设计熟悉以单片机核心的应用系统开发的全过程,掌握硬件电路 设计的基本方法和技术,掌握相关电路参数的计算方法。最终较好的完成了设计, 达到了预期的目的,完了最初的设想。但是由于时间和个人暂时的能力的原因, 整个系统看起来还是显得非常的简单,只实现了一些最基本的功能,还有许多不 足和可以扩展的地方。毕业设计的完成,为我的大学学习生活画下了最后一笔。应该感谢的人很多, 首先感谢学院给我们提供了一个展现自己的舞台,在长江职业技术学院这个良好 的学习环境中,我们得到了很多锻炼的机会,使得我们的动手能力和专业技能都 有了很大的提高。其次要感谢教单片机的邓柳老师的悉心教导和全程负责

27、毕业报 告完成的陈卉老师,还有帮助我完成的学校电子竞赛组的同学。是你们为我创造 了良好的学习和完成毕业设计的环境,你们的支持和鼓励使我对这次的设计完成 有了信心和动力,使我能够顺利地完成课题的设计工作,在此向这些帮助我的人 致以诚挚的谢意。最后,还要特别感谢我的父母,养育之恩,无以回报,你们永 远健康快乐是我最大的心愿。正是在爸妈身体和精神的养育下才让我得以全身心 投入学习和研究中,顺利完成学业。即将踏上社会了,在人生的又一个十字路口上,我将带着你们的期望和关怀, 在将来的工作岗位上勤奋实干,积极进取,用优异的成绩来回报大家对我的关心 和帮助!参考文献1彭伟 单片机C语言程序设计实例100例

28、电子工业出版社2009年5月;2 王文杰 许文斌 主编 单片机应用技术 冶金工业出版社 2008 年 6 月; 3张福祥 C 语言程序设计 辽宁大学出版社 2007 年2月;4 郭天祥 十天学会单片机 哈尔滨工程大学出版社 2007 年 6月;附录:主程序/ 名称:用DS1302与1602LCC设计的可调式电子日历与时钟/ 说明:本例会自动调节合法日期时间,对于星期的调节会在/调整年月日时自动完成,闰年问题也会自动判断。/#include <reg51.h>#include <string.h>#define uchar unsigned char#define uin

29、t unsigned intsbit SDA=P1A0; /DS1302 数据线sbit CLK=PM1; /DSB1302 时钟线sbit RST=P1A2; /DS1302 复位线sbit RS=P2A0;/LCD寄存器选择sbit RW=P2A1;/LCD读/写控制sbit EN=P2A2;/LCD启用sbit K1=P3A4;/选择sbit K2=P3A5;/加sbit K3=P3A6;/减sbit K4=P3A7;/确定uchar tCount=0;/ 一年中每个月的天数,二月的天数由年份决定uchar MonthsDays=0,31,0,31,30,31,30,31,31,30,3

30、1,30,31;/周日,周一到周六0,1-6读取DS1302时分别是1-7uchar *WEEK="SUN","MON","TUS","WEN","THU","FRI","SAT";/LCD 显示缓冲uchar LCD_DSY_BUFFER1="DATE 00-00-00 ";uchar LCD_DSY_BUFFER2="TIME 00:00:00 ";uchar DateTime7; / 所读取的日期时间char

31、Adjust_Index=-1; / 当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6)(不调节秒周)写数据的程序uchar Change_Flag="-MHDM-Y" / (分,时,日,月,年)/延时,向DS1302写、读一字节以及从 DS1302旨定位置度、/延时void DelayMS(uint x)uchar i;while(x-) for(i=0;i<120;i+);/向DS1302写入一个字节void Write_A_Byte_TO_DS1302(uchar x) uchar i;for(i=0;i<8;i+)SDA=x&1

32、; CLK=1; CLK=0; x>>=1;/从DA1302读取一字节uchar Get_A_Byte_FROM_DS1302() uchar i,b,t;for(i=0;i<8;i+)b>>=1;t=SDA;b|=t<<7;CLK=1;CLK=0;/BCD 码转换return b/16*10+b%16;/从DS1302旨定的位置读数据 uchar Read_Data(uchar addr) uchar dat;RST=0;CLK=0;RST=1;Write_A_Byte_TO_DS1302(addr);dat=Get_A_Byte_FROM_DS13

33、02();CLK=1;RST=0;return dat;/向DS1302某地址写入数据 void Write_DS1302(uchar addr,uchar dat) CLK=0;RST=1;Write_A_Byte_TO_DS1302(addr);Write_A_Byte_TO_DS1302(dat);CLK=0;RST=0;/ 设置时间 void SET_DS1302()uchar i;Write_DS1302(0x8E,0x00);/ 写控制字,取消写保护 for(i=1;i<7;i+) / 分时日月年依次写入/ 分的起始地址 10000010(0x82), 后面续依次是时,日,月

34、,周,年, 写入地址每次递增 2Write_DS1302(0x80+ 2*i,(DateTimei/10<<4)|(DateTimei%10);Write_DS1302(0x8E,0x80);/ 加保护/ 读取当前日期时间/void GetTime()uchar i;for(i=0;i<7;i+)DateTimei=Read_Data(0x81+2*i);/1602LCD 的若干显示控制代码。/uchar Read_LCD_State()读 LCD犬态uchar Read_LCD_State()uchar state;RS=0;RW=1;EN=1;DelayMS(1);sta

35、te=P0;EN=0;DelayMS(1);return state;/void LCD_Busy_Wait() 忙等待void LCD_Busy_Wait()while(Read_LCD_State()&0x80)=0x80);DelayMS(5);/void Write_LCD_Data(uchar dat) 向 LCD写数据void Write_LCD_Data(uchar dat)LCD_Busy_Wait();RS=1;RW=0;EN=0;P0=dat;EN=1;DelayMS(1);EN=0; /void Write_LCD_Command(uchar cmd)写 LCD旨

36、令void Write_LCD_Command(uchar cmd)LCD_Busy_Wait();RS=0;RW=0;EN=0;P0=cmd;EN=1;DelayMS(1);EN=0; /void Init_LCD()LCD 初始化void Init_LCD()Write_LCD_Command(0x38);DelayMS(1);Write_LCD_Command(0x01);DelayMS(1);Write_LCD_Command(0x06);DelayMS(1);Write_LCD_Command(0x0c);DelayMS(1); /void Set_LCD_POS(uchar P)

37、设置液晶显示位置 void Set_LCD_POS(uchar p)Write_LCD_Command(p|0x80);/在LCD上显示字符串void Display_LCD_String(uchar p,uchar *s)uchar i;Set_LCD_POS(p);for(i=0;i<16;i+)Write_LCD_Data(si); DelayMS(1);/ 日期与时间值转换为数字字符void Format_DateTime(uchar d,uchar *a)a0=d/10+'0'a1=d%10+'0'/ 判断是否为闰年uchar isLeapYea

38、r(uint y)return(y%4=0&&y%100!=0)|(y%400=0);/ 求自 2000.1.1 开始的任何一天是星期几/ 函数没有通过,求出总天数后再求星期几,/ 因为求总天数可能会超越 uint 的范围。 void RefreshWeekDay()uint i,d,w=5;/ 已知 1999.12.31 是周五 for(i=2000;i<2000+DateTime6;i+) d=isLeapYear(i)?366:365; w=(w+d)%7;d=0;for(i=1;i<DateTime4;i+) d+=MonthsDaysi; d+=DateT

39、ime3;/保存星期,06表示星期日至周六,为了与 DS1302的星期格式匹配,返回值需 要加 1DateTime5=(w+d)%7+1;/void DateTime_Adjust(char x)switch(Adjust_Index)case 6:/ 年 00-99 if(x=1&&DateTime6<99) DateTime6+; if(x=-1&&DateTime6>0) DateTime6-;/ 获取 2 月天数 MonthsDays2=isLeapYear(2000+DateTime6)?29:28;/ 如果年份变化后当前月份的天数大于上限

40、则设为上限 if(DateTime3>MonthsDaysDateTime4)DateTime3=MonthsDaysDateTime4;RefreshWeekDay();/ 刷新星期 break;case 4:/ 月 01-12 if(x=1&&DateTime4<12) DateTime4+; if(x=-1&&DateTime4>1) DateTime4-;/ 获取 2 月天数 MonthsDays2=isLeapYear(2000+DateTime6)?29:28;/ 如果月份变化后当前月份的天数大于上限则设为上限 if(DateTim

41、e3>MonthsDaysDateTime4)DateTime3=MonthsDaysDateTime4; RefreshWeekDay();/ 刷新星期 break;case 3:/ 日 00-28/29/30/31 ;调节之前首先根据年份得出该年中 2 月的 天数MonthsDays2=isLeapYear(2000+DateTime6)?29:28; / 根据当前月份决定调节日期的上限 if(x=1&&DateTime3<MonthsDaysDateTime4)DateTime3+;if(x=-1&&DateTime3>0) DateTi

42、me3-;RefreshWeekDay();/ 刷新星期break;case 2:/ 时if(x=1&&DateTime2<23) DateTime2+; if(x=-1&&DateTime2>0) DateTime2-; break;case 1:/ 分if(x=1&&DateTime1<59) DateTime1+; if(x=-1&&DateTime1>0) DateTime1-; break;/定时器0每秒刷新LCD显示void T0_INT() interrupt 1TH0=-50000/256;

43、TL0=-50000%256;if(+tCount!=2) return;tCount=0;/ 按指定的格式生成待显示的日期时间串Format_DateTime(DateTime6,LCD_DSY_BUFFER1+5);Format_DateTime(DateTime4,LCD_DSY_BUFFER1+8);Format_DateTime(DateTime3,LCD_DSY_BUFFER1+11);/ 星期 strcpy(LCD_DSY_BUFFER1+13,WEEKDateTime5-1);/ 时分秒Format_DateTime(DateTime2,LCD_DSY_BUFFER2+5);F

44、ormat_DateTime(DateTime1,LCD_DSY_BUFFER2+8);Format_DateTime(DateTime0,LCD_DSY_BUFFER2+11);/ 显示年月日,星期,时分秒Display_LCD_String(0x00,LCD_DSY_BUFFER1);Display_LCD_String(0x40,LCD_DSY_BUFFER2); /- 键盘中断( INT0) void EX_INT0() interrupt 0if(K1=0) / 选择调整对象( Y M D H M)while(K1=0);if(Adjust_Index=-1|Adjust_Index=1) Adjust_Index=7; Adjust_Index-;if(Adjust_Index=5) Adjust_Index=4;/ 跳过对星期的调节 LCD_DSY_BUFFER213=''LCD_DSY_BUFFER214=Change_FlagAdjust_Index;LCD_DSY_BUFFER215=''else if(K2=0)/ 加while(K2=0); DateTime_Adjust(1);els

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1