找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1278|回复: 0
打印 上一主题 下一主题
收起左侧

基于单片机的光能电子时钟设计

[复制链接]
跳转到指定楼层
楼主
ID:729128 发表于 2020-4-15 18:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
温度显示:本设计采用DS18B20芯片,作为常用的数字温度传感器.DS18B20具有硬件开销低,抗干扰能力强,对于温度测控显示误差小等优点。并且采用单线结构,也就是说只需要一根线和cpu连接,就可以实现在不依赖其他外部部件的情况下输入或输出串行数据。并有直接使用信号线供电的特点。在正常情况下,电源可以测量范围为3.2v~5.0v的电压,并且相对于同种芯片测量准确度更加高,测温范围为:零下五十五度到一百二十度,在零下十度~八十五度范围内,准确度可以达到上下浮动零点五的误差。当转换数位为12位时,温度基础分辨率可以达到0.0598C°。程序中所有的数字精度及时间的转换都可以用简单的编译程序控制来实现,可以实现短时性上下限报警设定的功能。用户利用一些常规的编程改变数字大小就可以控制报警器的阈值。
1.2.2其他模块
  键盘控制模块:本设计采用的是独立式键盘。每一个按键都单独占用了一根I/O接口,并且各个按键接口都相互独立,也就是说单个按键并不会影响其他I/O接口的工作状态。所以通过程序很容易就知道输入线的电平状态可以很轻松判断哪个按键被按下了。该种设计使得每个按键有单独的功能,更加便于操作。
  显示模块:使用LCM12864液晶显示屏显示数字。液晶显示屏具有体积小,表面积大,成像清晰稳定,质感轻薄,电耗低抗干扰能力强等优点。

第二章 系统硬件设计
2.1时钟硬件选择
2.1.1单片机选择。
经过同种单片机的数据对比,本时钟采用了常规的AT89C51芯片,单片机计算效率高,程序运算简单,可用度高,只需要一些简单的编程就可以实现对所有的的算法及逻辑控制,并且因为其耗能少,体积小,成本低廉技术商业化程度高等优点,使AT89C51在各个领域都有广泛的使用。
AT89C51相比其他芯片而言具有低电压高性能的特性,而且是所带4k字节的flash存储器的单片机。在正常情况下,可擦除只读类的储存器的单片机能够反复擦除九十次以上。而由AT89C51单片机是使用了非常高的精密器件制作工艺所制作,与工业标准的MCS-51输出管脚和指令集兼容。AT89C51单片机的存在为高级算效率低制造成本的嵌入式控制系统提供了可能。

AT89C51单片机
图2-1
各个管脚说明:
VCC:为电路供电电压。
GND:端口接地。
PO:在进行编程时,原码由该口输入。当系统开始校验的时候原码由此口所输出与此同时p0外部电压被拉高。
P1:在系统进行编程或者校对时, 该引脚接口将所有第八位的地址接收。
P2:同上在系统进行编程或校验时接收高八位地址信号以及控制信号。
P3:作为输入,将低电平转换为高电平
2.1.2显示模块
方案一:使用LCM12864液晶显示屏显示数字。液晶显示屏的优势是相对传统显示屏在重量上占比较轻厚度也更加薄、便于携带和运输。能耗更低、几乎不存在有辐射的危险。而且在显示模式上有着直角显示以及成像稳定不花屏等优点,可观测的实际面积较大,图像更好,抗锯齿干扰能力更强的特点。
方案二:采用点阵数码管显示,所谓的点阵数码管就是由发光二极管均匀排版的成品,通过列矩阵控制的方式点亮相应的二极管从而形成可控制的的显示单元,不过该种方式更适用于显示文字,如果仅用于显示数字则性价比较低。
    方案三:采用传统的LED数码管显示。同比其他方式而言使用数码管的优势在于:损耗更低,使用寿命更长,对环境要求更低,容易维护,高精度,重量小,操作简单但可显示的信息相对有限,一般只能用作为数字显示。
根据需求及上述所论,决定采用方案一。
2.1.3键盘模块
    方案一: 使用独立式键盘。每一个按键都单独占用了一根I/O接口,并且各个按键接口都相互独立,也就是说单个按键并不会影响其他I/O接口的工作状态。所以通过程序很容易就知道输入线的电平状态可以很轻松判断哪个按键被按下了。该种设计使得每个按键有单独的功能,更加便于操作。优点是软件结构简单,电路配置灵活。
    方案二:采用矩阵式键盘,相比独立式键盘矩阵式键盘更适用于对按键数量要求更多的场合。矩阵式键盘一般由行线和列线组成,所有的按键都分布在每行与每列的交叉点上,这样可以节省I/O接口。此键盘扩展性好,但操作相对更加复杂。对于容错率要求更高。
因此根据作品实际要求,我们采用方案一。
2.1.4时钟芯片模块
时钟芯片我们使用了DS1302时钟芯片,DS1302是一个价格低廉,简单方便,用法多样的实时时钟芯片,与其他时钟芯片不同的是,它是一个在性能上更加稳定并且对于电压要求更低的实时时钟芯片,具备31字节RAM,并且可以实现在断电状态下完成一次性传输多个ram数据和多字节的时钟信号。在功能方面ds1302可以实现提供年、月、礼拜、天、时、分、秒的功能。并且其对工作电压电压压宽要求更低,支持双电源供电。用于数据记录,特别是对某些具有特殊意思的数据点的记录上,能实现数据与出现该数据的时间同时记录,广泛应用于各个测量系统中。因此,同比其他时钟芯片,我们采用DS1302。
2.2系统硬件框图
电子时钟电路是由AT89C51单片机为控制核心,具有在线编程功能,功耗相对较低支持在超低电压的状态下持续工作,显示部分采用12864点阵液晶屏显示,整个电子时钟系统由太阳能供电系统供电系统硬件框图如下:

图2-4
2.3液晶显示模块设计
2.3.1概述
12864点阵.液晶显示模块.可以显.示字母、数字符号、中.文字型.及图形,具有.绘图及文.字画.面.混..合.显.示.功.能。是一-种具.有4位/8位并行、2线.或3线串.行多.种.接.口方式,内部含有国标- -级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128X64,内置8192个16*16点汉字,和128个16*8点ASCII字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示.8X4行.16X16点阵的汉字,也可.完成图形显示.低电压低功耗是其又一- 显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构或显示程序.都要简洁得多,且该模块的价格也略低于相同.点阵的图形液晶模块。1286.4由20个引脚其.哥哥引脚功能如下图所示:


2.3.2单片机接口设计
VCC和直.流电源相连接,当+5V电压在稳定在正常范围时,程序数据可读写,当电压低于4. 25V时,读写被禁止,但计时功能依然可以进行,计时器供电切换为内部锂电池供电: VSS 与BLK引脚接地: DB0~DB7是双向地址/数据复用线,与单片机2口相接, 实现数据传送: VEE 与VO间接一个滑动变阻器.

图2-5
2.3.3屏幕显示
  页面显示分为三个界面,通过按键切换,分别为开机界面、主界面及闹钟界面。主
界面包括时间,星期,温度,节日,若该日不是节日则显示上午下午、闹钟图标闹钟界面为闹钟及秒表。
2.4时钟芯片模块
2.4.1时钟芯片概述
随着电子技术的不断发展,电子时钟技术已经非常的完善,通过芯片传递的电子信号计时,将其时间数据经单片机输出,大大提高了电子时钟的稳定性和准确性。DS1302是一个价格低廉,简单方便,用法多样的实时时钟芯片,与其他时钟芯片不同的是,它是一个在性能上更加稳定并且对于电压要求更低的实时时钟芯片,具备31字节RAM,并且可以实现在断电状态下完成一次性传输多个ram数据和多字节的时钟信号。在功能方面ds1302可以实现提供年、月、礼拜、天、时、分、秒的功能。并且其对工作电压电压压宽要求更低,支持双电源供电。用于数据记录,特别是对某些具有特殊意思的数据点的记录上,能实现数据与出现该数据的时间同时记录,广泛应用于各个测量系统中。用于数据记录,特别是对某些具有特殊意思的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中
其引脚分布如下:

图2-6
2.4.2时钟芯片原理
A、引脚功能及连接
DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。X1和X2是振荡源,外接32.768kHz晶振。CE是复位/片选线,通过把CE输入驱动置高电平来启动所有的数据传送。CE输入有两种功能:首先,CE接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,CE提供终止单字节或多字节数据的传送手段。当CE为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中CE置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电运行时,在Vcc>2.0V之前,CE必须保持低电平。只有在SCLK为低电平时,才能将CE置为高电平。I/O为串行数据输入输出端(双向)。SCLK为时钟输入端。
    B、DS1302的控制字节
DS1302 的控.制字如图2-8所示。控制字节的.最高有效位(位.7)必须.是逻.辑1,如果它为0,则不能把数.据写入DS1302中,位6如果为0,.则表示.存取日历时钟数据,为1.表示.存取RAM数据;位5至.位1指示操作单元的地址;最低.有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制.字节总是从最.低位.开.始输.出。

图2-7
C、数据输入输出(I/O)
在控.制指令字输.入后.的下一个SCLK时钟的上.升沿时,数据.被写入.DS1302,数据输入从低位即位0开始。同样,在紧跟.8位的控.制指令字后的下一个SCLK脉冲.的下.降沿读出.DS1302的数据,读出.数据时.从低位0位到高位7。
D、DS1302的.寄存.器
 DS1302有12. 个寄存器,其中有.7个寄存器与.日历、时钟相关,.存放的数.据位.为BCD码形式。 此外,DS13.02 还有年.份寄存器、控制寄存器、充电寄.存器、时钟突发寄存器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读.写.除.充电寄存器外的所.有寄存器.内容。 DS1302与RAM相关的寄存.器.分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字.节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为..写操作;另一.类为突发方式.下的RAM寄存器,此方式.下可一次.性读写所有.的RAM的31个字节,命令控制.字为FEH(写)、FFH(读)。
2.5供电系统的选择

图2-8

太阳能电池板:作为整个供电系统中的核心部分,太阳能电池板的主要作用就是将光能转换为电能,并把这些转换来的电能分流,一部分用于系统正常运作耗电,多出的部分送到蓄电池中储存起来用于无光照时使用,因为生产工艺相对较为复杂所以太阳能电池板也是整个系统中价值最高的部分,并且太阳能电池板的质量和成本直接决定了整个电子时钟系统的质量与成本。
    太阳能控制器:该部分的具体作用就是控制整个太阳能电池板各个区域的工作状态,而且还能起到对蓄电池的保护作用,具体实现在充电保护和过放电保护两个阶段。一般情况下,在某部分温度过高时,温度控制器还能提供温度补偿功能。但这种控制器工艺要求更高造价也更为昂贵。
   
2.5.1太阳能板蓄电池的概括
太阳能板方阵在光照下开始工作,当光照越强输出功率也就越大,当晚上或者阴雨天等光照不足的情况下,由白天或光照充足时蓄电池所储存的电能进行放电维持系统整体的用电消耗,所以太阳能光伏发电系统对储能设备的要求比较高,其作用体现为储能并且为太阳能光伏发电工作阵和工作点起到一定的稳定作用。
      蓄电池的选型:首先我们要统计我们每天所需要的电量总值,一般情况下我们的设备平均没天耗电28mA左右,则1天的功耗为5V*0. 028A*24h=3. 36wh,由于大部分设备的耗.电.值会受到环境温度以及自身温度的影响,所以需要计算出每天各个时段的平局损耗。从而作为我们选择蓄电池的标准.,假定我们采用12V.蓄电池,考虑到在没有太阳的阴雨天可使充满电的电池连续工作三个月,则需电池容量为3.36wh*90/12V/50%=50.4Ah.

2.5.2太阳能电池板的概括及选型

    由单体太阳能电池封装成.满足一定电压和功率的小组合,根据需要由小组合构成太阳能光伏发电系统方阵。太阳能电池可以串联,为得到需要的方阵电压:可将太阳能电池组串联起来,串联后的电流取决于电流最小组件,串联后输出电压是单体电压之和,即U总=U1+2+3....为获得较大的输出电流,可把太阳能电池组件并联,并联后的电流是电池组件电流之和,即总电流=11+I2+... +In
太阳能电池方阵.由单体太阳能电池封.装成.满足一定电压和功率.的小组合,根据.需.要可由小.组合构成太阳.能电池光伏发电系统方阵,太阳能.电池方阵工作电压-般为负载工作电压的1.4倍。
计算太.阳.能.电.池.板的功率:按每天有效日照6小时计算,使电池.充电3天后可保证设备.60天的.用电量,再考虑到充电效率.和充电过程..中的损耗,太阳能板的输出功耗为3.6WH*60/3/6h/70%=25. 7w.其中70%是充电过程.中太阳能.电池板的实际.使用功率。另.外各地.区的日照.时间不同,可适当.进行修改。
按照两种容量方案计算,完成了太阳电源的设计:
1、测量的主要参数:
电子万年历系统输入电压5V,输出电流50mA,当地日照时数7~8个小时
2、蓄电池容量经计算得出为45AH
3、太阳能电池容量阵列输出功率为25.7W综合以上结果,太阳能电源设计为:
蓄电池:采用含.铅酸蓄电池,容量4.5AH,采用一个.容量为60.AH的蓄电池.,太阳.能阵列,输.出功率.为25. 7W,采用标.准模块.输出容.量为25~38W, - 块正好。
2.5.3太阳能电源安装使用中注意的问题
1、阵列板选择安装.放置在无遮挡太阳.光和.避风处。
2、太阳能电池列阵板配套的蓄电池在第一次使用时,要先充电到额定容量,不可过充或过放。
3.注.意定.期维护.工作。此电源系.统经济可靠,安装.方便,利于维护,在实践中取得了满意的效果。
2.5.4太阳能电源存在的问题
目前,太阳能电池产业发展的瓶颈主要有2方面问题:
第一.是价.格.问题。首先要研.制能稳定获得高.效率且低成本的半导体材.料:其次是能用低.成本.工艺路线生产这种光伏电池。从成.本上讲,太阳.能电.池仍然.是目前.常规.能源中成本最高的,当前.的.成.本对比如下表:


表2-2
    另一个是效率问题。在光电转换过程中,由于一部分光谱能量过小小于半导体的能量间隙,这部分光谱对太阳能板生成电流没有贡献所以并不是所有入射光都可以被太阳能板所吸收,并且转化为电流。这部分能量就会以热能的形式释放出去,所以并不是多有的入射光谱都能被电池吸收,并完全转化成电流。一般情况下,单一.电池.的.最高效.率约在.23%左右,但是因为制.造工艺过程复杂,产量太.低,造成价.格偏高,如果用于电.子时钟不符合经济效益,这也是目.前光伏电池发展的最大.瓶颈。

第三章 系统软件设计
主程序的主要功能为操纵各个子程序从而实现软件的功能。主程序流程图如图3-1所示。
3.1初始化子程序:

图3-1
3.1初始化子程序:

图3-2 DS1302初始化子程序

图3-2 LCM12864初始化流程图

图3-3


第四章 系统整体使用与调试
4.1硬件调试

本系统是一个基于AT89C51单片机的.时间显.示系统,能显示.公.历年、月、日、时、分、秒以及.温度、星期、节日等信息。系统所用时钟芯片.DS1302具有高性能.、低功.耗的特点.,使本系统编.程方便,同.时.功.能也强。采用AT89C51.单片机的电子时钟系统.可以很好的改善.传统采用模拟电路引起的计时不准确,不可靠,一致性差等问题。此系统计时精确,价格低廉,可以广泛应用在生活中,学习和工作任何领域,并且起到重要作用。
    电子时钟.电路.系统.较大,对于搭接电路就更能.不可轻视,庞大的.电路系统中只要出于.一处的错.误,则会.对检测造.成很大的.不便,而且电路的交.线较多,对于.各种锋.利.的引脚.要注意处理,否则.会刺破.带有包皮的导线,则会对.电.路造成.短路现象。
在本电子时钟的设计调试中遇到很多问题。但回想这些问题,只要认真思考都是可以避免的,一下为遇到的主要问题:
(1)在绘制PCB图时,焊盘的孔径不一致,导致最后在雕刻时,反复打孔,浪费时间。
解决办法是:在把画好的pcb导入到声称雕刻码的软件时,在焊盘选项可以很容易看到不一-致的焊盘的孔径,然后改正。
(2)在调试蜂鸣器时,发现蜂鸣器不响。
解决办法是:首先检查三极管是否坏掉,其次检查程序中是否出现错误。如果是三极管坏了,那么就是在焊接三极管是,焊烙铁长时间接近三极管,导致三极管坏掉,如果是程序问题,那么就直接修改程序中的bug.
(3)在焊接元器件时,焊反了导致通电烧片子。
解决办法是:在焊接前应该看清楚元件的正反,然后插到板子上,这样焊上去一般不会出现问题的。;

4.2软件测试

电子时钟是多功能的数字型系统,可以看当前的日期、时间。由于功能多,所以它的程序设计也较为复杂,在编写程序和调试时出现了相对较多的问题。最后经过多次的模块子程序的修改,一步步的完成,最终完成了软件设计。在软件的调试过程中主要遇到的问题如下:

(1)调试程序出现bug时,很难找到bug所在。
解决办法:从main程序开始,一句一句检查,并且揣摩其逻辑是否正确,如果不正确立即修改,然后在调试,直到程序中的bug为零。
(2)程序所实现的功能与自己预期的情况相差很远
解决办法:找到此功能所对应的程序代码,认真分析其中的逻辑看是否与自己的预期设想一致,如果不一致就修改直到修改正确为止。
(3)多个功能- -起实现时,出现不兼容情况。
    解决办法:首先找到多个功能所实现的共同特点,然后再找到不同点,在把他们不同条件相互交换,这样当一个功能实现时,另个-功能就不会出现干扰情况。

结论
     时钟.历史.悠久,种类繁多,随着科学.技术的发展和进步,其技.术性能也在逐步提高。本课题的.题目是设计太阳能电子时钟系统,该电子时钟.主要采用AT89C54单片机作为控制核心,有DS1302时钟.芯片提供时钟、12864 液晶显示屏显示,提高系统稳定性,采用数字. .温度传感器DS18B20芯片.控制温度显示,独.立式键盘按键切换功能。同时本设计.实用太阳能电源进行供电,普及了洁净、环保、可持续性发展的思想,把太阳能.带入人们日常生活的细微处,将环保与节能并举。总结如下:由于时间.紧迫,工作量大,设计仍有不足之处,有.待改进,提出以下几点.需要.改进的地方:
1、虽然太. .阳能作为一种巨大、清洁、普遍的.可再生能源,将有望成为未来的可靠能源,但应用还为普及,成本也较高,努力降低.太阳能供电成本是当前一-大难题。
2、程序设计逻辑性强,期间运行优良,但为了使系统更完善,应对系统进行更深的软件抗干扰设计。
随着人民.生活水平.的日益提高,人民不仅仅满足精确.时间的显示,更加注意其外观、新潮的外观能更加吸.引消费者的注意,所以我们.设计了精美,新颖切实用,更具人性化的外观。电子时钟添.加了更多功能,例如温度显示,节日显示,秒表等,更多的功能可以让用户使用更加方便。随着.经济水平的不断发展、科技的不断进步及人们.对生活环境的逐渐重视,太阳能.类的清洁能源产品.将越来越.得到青眯,这类产品将具更见广阔的前景。

参考文献
[1]罗运俊.太阳能利用技术【D】,化学工业出版社.2011.
[2]钱伯章.太阳能技术与应用【J】,科学出版社.2010.
[3]张毅刚,单片机原理及应用【D】,高等教育出版社.2014.
[4].皮大熊.单片机课程设计指导书【D】,北京理工大学出版社.2010.
[5].楼然苗.51系列单片机设计实例【D】.北京航空航天出版社】.2004.
[6].凌玉华,单片机原理及应用系统设计【D】,中南大学出版社.2006.
[7].胡汉才,单片机原理及应用【D】,清华大学出版社.2004.
[8].徐江海.单片机实用教程【D】.机械工业出版社2007.

致谢
在毕业设计论文即将完成之际,我想对所有曾经给过我们帮助和支持的人表示衷心的感谢。
首先,感谢我们的父母,是他们给了我们无私的爱,我深知他们为了我们求学和生活所付出的巨大的牺牲和努力,至今我一直无以回报,在此,仅表达我们对他们的深深思念和感恩。
感谢我们的指导老师陆程。她在毕业设计上给了我们大量的指导,让我们学会了很多知识,掌握了单片机的使用,c语言的应用以及太阳能供电的基本原理,也获得了实践锻炼的机会。她对我们的严格要求将使我们终身受益。另外,还要感谢学校为我们提供的良好的实习环境及生活环境,让我们在这个陌生的环境里感受到温暖。感谢大学三年里的老师们,他们三年来对我们的教育,让我们懂得了如何做事,更让我们明白了如何做人。感谢一起的同学们,他们是我们学习、工作、生活上的伙伴,也是面对困难与挫折是的并肩战友。还有许许多多给了我们指导和帮助的朋友,在此一并表示衷心的感谢,你们的帮助,我会一直铭记在心!最后,衷心感谢在场的各位审阅论文的老师,谢谢你们在百忙之中抽出时间来简评本次答辩。

附录
//-------------------------------------
// 名称:用DS1302与12864LCD设计的可调电子日历与时钟
//---------------------------------------
// 说明:本例运行时会以PC时间表为默认时间开始,运行过程中可以通过K1键
//       选择调节对象,所选中的调整对象会反白显示,用K2,K3键进行加减,用K4键保存。
//       本例会自动将时间调节控制为合法日期时间,对于星期的调节会
//        在调整年月日时自动完成,闰年问题也会自动判断。
//-------------------------------------------
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD_DB_PORT P0         // 液晶数据线端口DB0-DB7
#define LCD_START_ROW 0xc0     //起始行命令
#define LCD_PAGE 0xB8         //页指令
#define LCD_COL  0x40         //列指令
bit Reverse_Display=0;//是否反相显示(白底黑字/黑底白字)
//液晶引脚定义
sbit SDA=P1^0;      //DS1302数据线
sbit CLK=P1^1;      //DS1302时钟线
sbit RST=P1^2;      //DS1302复位线
sbit DI=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
sbit CS1=P2^3;
sbit CS2=P2^4;
sbit CS3=P2^2;

char Adjust_Index=-1;  //当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6)
uchar MonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};   // 一年中每个月的天数,二月的天数由年份决定
uchar DateTime[7];//所读取的日期时间
//DS1302函数声明
void Write_Byte_TO_DS1302(uchar X); // 向DS1302写入一个字节
uchar Read_Byte_FROM_DS1302();        //从DS1302中读取一个字节
uchar Read_Data_FROM_DS1302(uchar addr);  //从DS1302指定位置读取数据    , 读数据
void Write_Data_TO_DS1302(uchar addr,uchar dat);  // 向DS1302指定位置写入数据, 写数据
void SET_DS1302();      //设置时间
void GetTime();          //读取当前时间
uchar Is_Leapyear(uint year); //判断是否为闰年
//12864LCD函数
void dht11();
extern void LCD12864_Initialization();
extern void Display_char(uchar P1,uchar L1,uchar *M) reentrant;
extern void Display_Word(uchar P2,uchar L2,uchar *M) reentrant;
extern void Datetime_Adjust(char X);
extern void SET_DS1302();      //  设置时间
//函数声明
void Initialization();//初始化函数
extern bit Reverse_Display;//是否反相显示(白底黑字/黑底白字)
extern uchar code Digits[];
extern uchar code WEEK_WORDS[];
extern uchar code Digits[];
extern uchar code DATE_TIME_WORDS[];
extern char Adjust_Index;  //当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6)
extern uchar MonthsDays[];   // 一年中每个月的天数,二月的天数由年份决定
extern uchar DateTime[7];//所读取的日期时间
sbit k1=P3^4;       //选择按键
sbit k2=P3^5;       //加
sbit k3=P3^6;       //减
sbit k4=P3^7;       //确定
uchar tcount=0;   
//水平与垂直偏移   
uchar H_Offset=0;   
uchar V_page_Offset=0;

//---------------------------------------------------------------
//    检查LCD是否忙
//--------------------------------------------------------------
bit LCD_IS_BUSY()
{
      LCD_DB_PORT=0xFF;
    RW=1;
    _nop_();
    DI=0;
    E=1;
    _nop_();
    E=0;
    return (bit)(P0&0x80);
}
//---------------------------------------------------------------
//    向LCD写入一个字节(一般用于发送命令)
//--------------------------------------------------------------
void Write_Byte_To_LCD(uchar comand)
{
   while(LCD_IS_BUSY());  
   LCD_DB_PORT=0xFF;
   RW=0;
   _nop_();
   DI=0;
   LCD_DB_PORT=comand;
   E=1;
   _nop_();
   E=0;
}
//---------------------------------------------------------------
//    向LCD写入数据
//--------------------------------------------------------------
void Write_Data_To_LCD(uchar dat)
{
   while(LCD_IS_BUSY());  
   LCD_DB_PORT=0xFF;
   RW=0;
   _nop_();
   DI=1;
   if(!Reverse_Display)       //根据Reverse_Display决定是否反相显示
       LCD_DB_PORT=dat;
   else
      LCD_DB_PORT=~dat;
   E=1;
   _nop_();
   E=0;
}

//********************************************************************
//1MS为单位的延时程序,不准确
//********************************************************************
void lcd_delay_ms(unsigned char m)
{
    unsigned char n;
    while(m--){
        for(n=0;n<125;n++)
            {;}
        }   
}

//---------------------------------------------------------------
//    初始化LCD
//--------------------------------------------------------------
void LCD12864_Initialization()
{
  CS1=1;
  CS2=1;
  Write_Byte_To_LCD(0x38);
    lcd_delay_ms(10);
  Write_Byte_To_LCD(0x0F);
    lcd_delay_ms(10);
  Write_Byte_To_LCD(0x06);
    lcd_delay_ms(10);
//  Write_Byte_To_LCD(LCD_START_ROW);
  Write_Byte_To_LCD(0x01);
    lcd_delay_ms(10);
}
//---------------------------------------------------------------
//    通用显示函数  从第P页第L列显示W个字节数据,具体显示的数据在r所指的数组中
//--------------------------------------------------------------
void LCD_Show(uchar P,uchar L,uchar W,uchar *r) reentrant
{
    uchar i;
    if(L<64)
          {
            CS1=1;
            CS2=0;
            Write_Byte_To_LCD(LCD_PAGE+P);
            Write_Byte_To_LCD(LCD_COL+L);
            if(L+W<64)
              {
                for(i=0;i<W;i++)
                   Write_Data_To_LCD(r);
              }
            else
              {
                for(i=0;i<64-L;i++)
                      Write_Data_To_LCD(r);
                CS1=0;
                CS2=1;
                Write_Byte_To_LCD(LCD_PAGE+P);
                Write_Byte_To_LCD(LCD_COL);
                for(i=64-L;i<W;i++)
                      Write_Data_To_LCD(r);
              }
           }
    else
      {
            CS1=0;
            CS2=1;
            Write_Byte_To_LCD(LCD_PAGE+P);
            Write_Byte_To_LCD(LCD_COL+L-64);
            for(i=0;i<W;i++)
                  Write_Data_To_LCD(r);
      }
}
//---------------------------------------------------------------
// 显示一个8×16点阵字符
//--------------------------------------------------------------
void Display_char(uchar P1,uchar L1,uchar *M) reentrant
{
   LCD_Show(P1,L1,8,M);
   LCD_Show(P1+1,L1,8,M+8);
}
//--------------------------------------------------------------------
// 显示一个16×16点阵字符 (汉字上半部分与下半部分分别处在相邻两页中)
//----------------------------------------------------------------------
void Display_Word(uchar P2,uchar L2,uchar *M) reentrant
{                                             
   LCD_Show(P2,L2,16,M);
   LCD_Show(P2+1,L2,16,M+16);
}
//--------------------------------------------------------------------
// 显示一个16×32点阵字符 (汉字上半部分与下半部分分别处在相邻两页中)
//----------------------------------------------------------------------
void Display_Word2(uchar P2,uchar L2,uchar *M) reentrant
{                                             
   LCD_Show(P2,L2,16,M);
   LCD_Show(P2+1,L2,16,M+16);
    LCD_Show(P2+2,L2,16,M+32);
    LCD_Show(P2+3,L2,16,M+48);
}


//*************************************************************************
//***********************DHT11*************************
//**************************************************************************

//sbit DATA = P1^3;        //定义数据引脚
//bit flag_1s,flag_200ms,tmp;

//----------------定义区--------------------//
uchar s1,s2,w1,w2;

sbit TRH = P1^3;//data数据端
unsigned char i;

typedef unsigned char unint8;
typedef unsigned char unint16;

unint8 TH_data,TL_data,RH_data,RL_data,CK_data;
unint8 TH_temp,TL_temp,RH_temp,RL_temp,CK_temp;
unint8 com_data,untemp,temp;
unint8 respond;

/*********************************************************************************/
void delayNOP()
{
         _nop_();
         _nop_();
         _nop_();
         _nop_();
}
/*********************************************************************************/


/*********************************************************************************/
// 毫秒级延时子程序
/*********************************************************************************/
void delay_ms(unsigned char ms)
{      
         unsigned char i;
         while(ms--)
         {
                  for(i = 0; i<250; i++)
                  {
                           _nop_();
                           _nop_();
                           _nop_();
                           _nop_();
                  }
         }
}
/*********************************************************************************/


/*********************************************************************************/
//5us级延时程序
/*********************************************************************************/
void delay_us()
{
         unint8 i;
         i--;
         i--;
         i--;
         i--;
         i--;
         i--;
}

/****************************************************************************/


/****************************************************************************/
//收发信号检测,数据读取
/****************************************************************************/
char receive()
{   
         unint8 i;
//         ST=0;
         com_data=0;
         for(i=0;i<=7;i++)   
         {
                  respond=2;
                  while((!TRH)&&respond++);
                  delay_us();
                  delay_us();
                  delay_us();
                  if(TRH)
                  {
                           temp=1;
                           respond=2;
                           while((TRH)&&respond++);
                  }
                  else
                           temp=0;
                  com_data<<=1;
                  com_data|=temp;   
         }
         return(com_data);  
}
/****************************************************************************/

//*--------写字节函数,向DS1302写入一个字节--------*//
void Write_Byte_TO_DS1302(uchar X)    // 向DS1302写入一个字节
  {
     uchar i;
     for(i=0;i<8;i++)
       {
         SDA=X&1;
         CLK=1;
         CLK=0;
         X>>=1;
       }
  }
//*--------读字节函数,从DS1302读取一个字节--------*//
uchar Read_Byte_FROM_DS1302()        //从DS1302中读取一个字节
{
   uchar i,byte,t;
   for(i=0;i<8;i++)
     {
      byte>>=1;
      t=SDA;
      byte|=t<<7;
      CLK=1;
      CLK=0;
     }
     //BCD码转换
     return byte/16*10+byte%16;
}
//-------------------------------------------------------------
//从DS1302指定位置读取数据    , 读数据
//---------------------------------------------------------------
uchar Read_Data_FROM_DS1302(uchar addr)  //从DS1302指定位置读取数据    , 读数据
   {
     uchar dat;
     RST=0;
     CLK=0;
     RST=1;
     Write_Byte_TO_DS1302(addr);  //向DS1302写入一个地址
     dat=Read_Byte_FROM_DS1302(); //在上面写入的地址中读取数据
     CLK=1;
     RST=0;
     return dat;
   }
//-------------------------------------------------------------
//向DS1302指定位置写入数据, 写数据
//---------------------------------------------------------------
void Write_Data_TO_DS1302(uchar addr,uchar dat)  // 向DS1302指定位置写入数据, 写数据
  {
      CLK=0;
       RST=1;
       Write_Byte_TO_DS1302(addr);
       Write_Byte_TO_DS1302(dat);
       CLK=1;
       RST=0;
  }
//-----------------------------------------------------------
// 设置时间
//---------------------------------------------------------
void SET_DS1302()      //  设置时间
{
   uchar i;
   Write_Data_TO_DS1302(0x8E,0x00); //写控制字,取消写保护
   // 分,时,日,月,年依次写入
   for(i=0;i<7;i++)
     {
      // 分的起始地址是10000010(0x82),后面依次是时,日,月,周,年,写入地址每次递增2
           Write_Data_TO_DS1302(0x80+2*i,(DateTime/10<<4)|(DateTime%10));
     }
   Write_Data_TO_DS1302(0x8E,0x80); //写控制字,加写保护
}
//--------------------------------------------------------
// 读取当前时间
//-------------------------------------------------------
void GetTime()          //  读取当前时间
{
  uchar i;
  for(i=0;i<7;i++)
    {
      DateTime=Read_Data_FROM_DS1302(0x81+2*i);
    }
}
//-------------------------------------------------------------------
// 判断是否为闰年
//-------------------------------------------------------------------
uchar Is_Leapyear(uint year)
{
  return (year%4==0&&year%100!=0)||(year%400==0) ;
}
//------------------------------------------------------------------
//     求自2000.1.1开始的任何一天是星期几?
//----------------------------------------------------------------------
void Refresh_Week_Day()
{
  uint i,d,w=5;  //已知1999年12.31是星期五
  for(i=2000;i<2000+DateTime[6];i++)
     {
        d=Is_Leapyear(i)?366:365;
        w=(w+d)%7;
     }
  d=0;
  for (i=1;i<DateTime[4];i++)
       {d+=MonthsDays;}
  d+=DateTime[3];
   //保存星期,0-6表示星期日,星期一至星期六,为了与DS1302的星期格式匹配,返回值需要加1
   DateTime[5]=(w+d)%7+1;
}
//-------------------------------------------------
//年,月,日和时,分++/--
//----------------------------------------------------
void Datetime_Adjust(char X)
{
  switch(Adjust_Index)
    {
       case 6:     //年调整,00-99
              if(X==1&&DateTime[6]<99)
                 {
                   DateTime[6]++;
                 }
              if(X==-1&&DateTime[6]>0)
                 {
                   DateTime[6]--;
                 }
              //获取2月天数
              MonthsDays[2]=Is_Leapyear(2000+DateTime[6])?29:28;
              //如果年份变化后当前月份的天数大于上限则设为上限
              if(DateTime[3]>MonthsDays[DateTime[4]])
                  {
                    DateTime[3]=MonthsDays[DateTime[4]];
                   }
               Refresh_Week_Day();  //刷新星期
              break;
       case 4:  //月调整 01-12
              if(X==1&&DateTime[4]<12)
                 {
                   DateTime[4]++;
                 }
              if(X==-1&&DateTime[4]>1)
                 {
                   DateTime[4]--;
                 }
                  //获取2月天数
              MonthsDays[2]=Is_Leapyear(2000+DateTime[6])?29:28;
              //如果年份变化后当前月份的天数大于上限则设为上限
              if(DateTime[3]>MonthsDays[DateTime[4]])
                  {
                    DateTime[3]=MonthsDays[DateTime[4]];
                   }
               Refresh_Week_Day();  //刷新星期
              break;
       case 3:     //     日调整00-28或00-29或00-30或00-31
                 //调节之前首先根据当前年份得出该年中2月的天数
              MonthsDays[2]=Is_Leapyear(2000+DateTime[6])?29:28;
              //根据当前月份决定调节日期的上限
              if(X==1&&DateTime[3]<MonthsDays[DateTime[4]])
                 {
                   DateTime[3]++;
                 }
              if(X==-1&&DateTime[3]>0)
                 {
                   DateTime[3]--;
                 }
              Refresh_Week_Day();  //刷新星期
              break;
       case 2:      //  时调整
              if(X==1&&DateTime[2]<23)
                 {
                   DateTime[2]++;
                 }
              if(X==-1&&DateTime[4]>0)
                 {
                   DateTime[2]--;
                 }
              break;
       case 1:      //  分调整
              if(X==1&&DateTime[1]<59)
                 {
                   DateTime[1]++;
                 }
              if(X==-1&&DateTime[4]>0)
                 {
                   DateTime[1]--;
                 }
              break;
        case 0:      // 秒调整
              if(X==1&&DateTime[1]<59)
                 {
                   DateTime[0]++;
                 }
              if(X==-1&&DateTime[4]>0)
                 {
                   DateTime[0]--;
                 }
              break;
    }
}

//-------------------------------------------------
// 与本程序有关的数字和汉字的点阵编码 DotMatrix.c
// -----------------------------------------------
//中文提示(纵向取模,字节倒序)
//年、月、日、星期、时、分、秒等汉字点阵(16×16)
uchar code DATE_TIME_WORDS[]={   
    0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00, //年
    0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00,
    0x00,0x00,0x00,0x00,0x00,0xFF,0x11,0x11,0x11,0x11,0x11,0xFF,0x00,0x00,0x00,0x00,//月
    0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x01,0x01,0x21,0x41,0x3F,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,//日
    0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00,//星
    0x00,0x48,0x46,0x41,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00,
    0x00,0x04,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00,//期
    0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00,
    0x00,0xFC,0x44,0x44,0x44,0xFC,0x10,0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,//时
    0x00,0x07,0x04,0x04,0x04,0x07,0x00,0x00,0x03,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,
    0x80,0x40,0x20,0x98,0x87,0x82,0x80,0x80,0x83,0x84,0x98,0x30,0x60,0xC0,0x40,0x00,//分
    0x00,0x80,0x40,0x20,0x10,0x0F,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,0x00,0x00,0x00,
    0x12,0x12,0xD2,0xFE,0x91,0x11,0xC0,0x38,0x10,0x00,0xFF,0x00,0x08,0x10,0x60,0x00,//秒
    0x04,0x03,0x00,0xFF,0x00,0x83,0x80,0x40,0x40,0x20,0x23,0x10,0x08,0x04,0x03,0x00
};

//一、二、三、四、五、六和天等汉字点阵(16×16)
uchar code WEEK_WORDS[]={
0x00,0x40,0x42,0x42,0x42,0x42,0x42,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x40,0x00,//天
0x00,0x80,0x40,0x20,0x10,0x08,0x06,0x01,0x02,0x04,0x08,0x10,0x30,0x60,0x20,0x00,
0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,//一
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,0x00,0x00,//二
0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x10,0x00,
0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00,//三
0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
0x00,0xFE,0x02,0x02,0x02,0xFE,0x02,0x02,0xFE,0x02,0x02,0x02,0x02,0xFE,0x00,0x00,//四
0x00,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x22,0x7F,0x00,0x00,
0x00,0x02,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0xC2,0x82,0x02,0x00,0x00,0x00,//五
0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x30,0x20,0x00,
0x10,0x10,0x10,0x10,0x10,0x91,0x12,0x1E,0x94,0x10,0x10,0x10,0x10,0x10,0x10,0x00,//六
0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x00,0x00,0x01,0x02,0x0C,0x78,0x30,0x00,0x00,
0x06,0x09,0x09,0xE6,0xF8,0x0C,0x04,0x02,0x02,0x02,0x02,0x02,0x04,0x1E,0x00,0x00,
0x00,0x00,0x00,0x07,0x1F,0x30,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10,0x00,0x00,/*"℃",0*/
};

//0-9等数字点阵(8×16)
uchar code Digits[]={  
    0x00,0x00,0xF0,0xF8,0x08,0x68,0xF8,0xF0,0x00,0x00,0x07,0x0F,0x0B,0x08,0x0F,0x07, //0
    0x00,0x20,0x20,0x30,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00,  //1
    0x00,0x30,0x38,0x08,0x88,0xF8,0x70,0x00,0x00,0x0C,0x0E,0x0B,0x09,0x08,0x08,0x00, //    2
    0x00,0x30,0x38,0x88,0x88,0xF8,0x70,0x00,0x00,0x06,0x0E,0x08,0x08,0x0F,0x07,0x00, //3
    0x00,0x00,0xF8,0xF8,0x00,0xE0,0xE0,0x00,0x00,0x03,0x03,0x02,0x02,0x0F,0x0F,0x02,//4
    0x00,0xF8,0xF8,0x88,0x88,0x88,0x08,0x00,0x00,0x08,0x08,0x08,0x0C,0x07,0x03,0x00,//5
    0x00,0xC0,0xE0,0x78,0x58,0xC8,0x80,0x00,0x00,0x07,0x0F,0x08,0x08,0x0F,0x07,0x00,//6
    0x00,0x08,0x08,0x88,0xE8,0x78,0x18,0x00,0x00,0x00,0x0E,0x0F,0x01,0x00,0x00,0x00,//7
    0x00,0x70,0xF8,0xC8,0x88,0xF8,0x70,0x00,0x00,0x07,0x0F,0x08,0x09,0x0F,0x07,0x00,//8
    0x00,0xF0,0xF8,0x08,0x08,0xF8,0xF0,0x00,0x00,0x00,0x09,0x0D,0x0F,0x03,0x01,0x00,//9
    0xF0,0x08,0xF0,0x80,0x60,0x18,0x00,0x00,0x00,0x31,0x0C,0x03,0x1E,0x21,0x1E,0x00,/*"%",0*/
  0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,/*"R",1*/
  0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,/*"H",2*/
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,/*".",0*/
};

uchar code fuhao[]=
{
    0x00,0x00,0x00,0x00,0x80,0xC0,0x40,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0xF0,0xFE,0x0F,0x01,0x00,0x00,0x00,0x00,0x01,0x07,0xFE,0xF0,0x00,0x00,0x00,
  0x00,0x3F,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x3F,0x00,0x00,0x00,
  0x00,0x00,0x01,0x03,0x06,0x0C,0x08,0x08,0x08,0x06,0x03,0x01,0x00,0x00,0x00,0x00,/*"0",0*/
  0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x01,0x01,0x01,0x01,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x08,0x08,0x08,0x0C,0x0F,0x0F,0x0C,0x08,0x08,0x08,0x00,0x00,0x00,0x00,/*"1",1*/
  0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x40,0x40,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,
  0x00,0x1E,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC1,0xFF,0x3E,0x00,0x00,0x00,
  0x00,0x00,0x00,0x80,0x40,0x30,0x18,0x0C,0x06,0x03,0x01,0x00,0xC0,0x00,0x00,0x00,
  0x00,0x0E,0x0D,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0E,0x03,0x00,0x00,0x00,/*"2",2*/
  0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x40,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x80,0xC1,0x7F,0x3E,0x00,0x00,0x00,0x00,
  0x00,0xC0,0xC0,0x00,0x00,0x01,0x01,0x01,0x03,0x02,0x06,0xFC,0xF0,0x00,0x00,0x00,
  0x00,0x03,0x07,0x04,0x08,0x08,0x08,0x08,0x08,0x04,0x06,0x03,0x00,0x00,0x00,0x00,/*"3",3*/
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x80,0x60,0x10,0x0C,0x03,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
  0x30,0x2C,0x26,0x21,0x20,0x20,0x20,0x20,0xFF,0xFF,0x20,0x20,0x20,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x0F,0x0F,0x08,0x08,0x08,0x00,0x00,0x00,/*"4",4*/
  0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,
  0x00,0x00,0xFF,0x00,0x80,0x40,0x40,0x40,0x40,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,
  0x00,0xC0,0xC3,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,
  0x00,0x03,0x04,0x04,0x08,0x08,0x08,0x08,0x08,0x04,0x07,0x03,0x00,0x00,0x00,0x00,/*"5",5*/
  0x00,0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x40,0x80,0x80,0x00,0x00,0x00,0x00,
  0x00,0xE0,0xFC,0x07,0x81,0xC0,0x40,0x40,0x40,0xC0,0x83,0x03,0x00,0x00,0x00,0x00,
  0x00,0x7F,0xFF,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,
  0x00,0x00,0x01,0x07,0x06,0x0C,0x08,0x08,0x08,0x0C,0x06,0x03,0x00,0x00,0x00,0x00,/*"6",6*/
  0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,
  0x00,0x0E,0x03,0x00,0x00,0x00,0x00,0x00,0xE0,0x18,0x06,0x01,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0xC0,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"7",7*/
  0x00,0x00,0x00,0x80,0xC0,0x40,0x40,0x40,0x40,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,
  0x00,0x3E,0x7F,0xF1,0xC0,0xC0,0x80,0x00,0x00,0x80,0x41,0x7F,0x1E,0x00,0x00,0x00,
  0xF0,0xFC,0x0E,0x02,0x01,0x01,0x01,0x03,0x07,0x0E,0x1E,0xFC,0xF0,0x00,0x00,0x00,
  0x01,0x03,0x06,0x04,0x08,0x08,0x08,0x08,0x08,0x04,0x06,0x03,0x01,0x00,0x00,0x00,/*"8",8*/
  0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
  0xFC,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFE,0xF8,0x00,0x00,0x00,
  0x01,0x03,0x07,0x0C,0x08,0x08,0x08,0x08,0x04,0x06,0xE1,0x7F,0x1F,0x00,0x00,0x00,
  0x00,0x07,0x07,0x08,0x08,0x08,0x08,0x0C,0x06,0x03,0x01,0x00,0x00,0x00,0x00,0x00,/*"9",9*/
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  //:
  0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0F,0x0F,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,/*"-",0*/
};



//----------------------------------------------------
// 主程序
//----------------------------------------------------
void main()
{

  Initialization();
    while(1)
      {
        if(Adjust_Index==-1)
            GetTime();
        read_TRH();
//        CS2=0; //左屏开显示
//      CS1=1;
      Display_char(6,0,Digits+s1*16);// Hz_Wo为某个汉字的首地址
        Display_char(6,16,Digits+s2*16);
//    CS2=1; //右屏开显示
//      CS1=0;
    Display_char(6,64,Digits+w1*16);
        Display_char(6,80,Digits+w2*16);
        }
}

void Initialization()//初始化函数
{
  IE=0x83;
    IP=0x01;
    IT0=0X01;
    TH0=-50000/256; // 写入初值
  TL0=-50000%256; //  写入初值
    TR0=1;
    LCD12864_Initialization();//液晶初始化函数
    //显示年的前面固定的两位
    Display_char(V_page_Offset,0+H_Offset,Digits+2*16);//显示2
    Display_char(V_page_Offset,8+H_Offset,Digits);     //显示0
   //-----------------------------------------------
   //在12864屏幕上固定显示汉字:年月日,星期,时分秒
   //---------------------------------------------------





     Display_Word(V_page_Offset,  80+H_Offset,DATE_TIME_WORDS+3*32);  //星
     Display_Word2(V_page_Offset+2,32+H_Offset,fuhao+10*64);          //:
     Display_Word2(V_page_Offset+2,80+H_Offset,fuhao+10*64);          //:
     Display_Word(V_page_Offset,  96+H_Offset,DATE_TIME_WORDS+4*32);  //期


}
//--------------------------------------------------------------
//      定时器0刷新LCD显示函数
//-------------------------------------------------------------
void T0_INT()interrupt 1
{
    TH0=-50000/256; // 写入初值
    TL0=-50000%256; // 写入初值
//     tcount++;
     if(++tcount!=2) return;
          tcount=0;
//         if(tcount%4==0)flag_200ms=1;
//    if(tcount==20)
//    {
//        tcount=0;
//        flag_1s=1;
//    }
     //年(后两位)
     Reverse_Display=Adjust_Index==6;
     Display_char(V_page_Offset,16+H_Offset,Digits+DateTime[6]/10*16);
     Display_char(V_page_Offset,24+H_Offset,Digits+DateTime[6]%10*16);
     //星期
     Reverse_Display=Adjust_Index==5;
     Display_Word(V_page_Offset,112+H_Offset,WEEK_WORDS+(DateTime[5]%10-1)*32);
     //月
     Reverse_Display=Adjust_Index==4;
     Display_char(V_page_Offset,40+H_Offset,Digits+DateTime[4]/10*16);
     Display_char(V_page_Offset,48+H_Offset,Digits+DateTime[4]%10*16);
     //    日
     Reverse_Display=Adjust_Index==3;
     Display_char(V_page_Offset,64+H_Offset,Digits+DateTime[3]/10*16);
     Display_char(V_page_Offset,72+H_Offset,Digits+DateTime[3]%10*16);
     //时
     Reverse_Display=Adjust_Index==2;
     Display_Word2(V_page_Offset+2,H_Offset,fuhao+DateTime[2]/10*64);
     Display_Word2(V_page_Offset+2,16+H_Offset,fuhao+DateTime[2]%10*64);
      //分
     Reverse_Display=Adjust_Index==1;
     Display_Word2(V_page_Offset+2,48+H_Offset,fuhao+DateTime[1]/10*64);
     Display_Word2(V_page_Offset+2,64+H_Offset,fuhao+DateTime[1]%10*64);
     // 秒
     Reverse_Display=Adjust_Index==0;
     Display_Word2(V_page_Offset+2,96+H_Offset,fuhao+DateTime[0]/10*64);
     Display_Word2(V_page_Offset+2,112+H_Offset,fuhao+DateTime[0]%10*64);   
}
//----------------------------------------------------------
//       键盘中断处理函数
//---------------------------------------------------------
void EX_INT0()interrupt 0
{
   if(k1==0)
         {
           if(Adjust_Index==-1||Adjust_Index==0)
             {Adjust_Index=7;}
           Adjust_Index--;
           if(Adjust_Index==5)
              {Adjust_Index=4;}     //跳过对星期的调节
         }
   else if(k2==0)             //    加
       {
          Datetime_Adjust(1);
       }
    else if(k3==0)             //    减
       {
          Datetime_Adjust(-1);
       }
    else if(k4==0)
       {
         SET_DS1302();
         Adjust_Index=-1;  //操作索引重设为-1,时间继续正常显示
       }

原理图:

毕业设计4.0完结篇 - 副本.doc

672.5 KB, 下载次数: 3, 下载积分: 黑币 -5

如目录

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表