您好,欢迎来到纷纭教育。
搜索
您的当前位置:首页基于ATS52单片机的电子时钟设计

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

来源:纷纭教育
摘 要

单片机在电子产品中的应用越来越广泛,特别是51系列的单片机,由于其使用方便、价格低廉等优势,在市场上占有很大的份额。ATS52就是51系列中的一个比较成熟的型号,它完全兼容51单片机的指令。

本文详细介绍了一款基于ATS52单片机数字钟的设计,通过多功能数字钟的设计思路,详细叙述了系统硬件、软件的具体实现过程。论文重点阐述了数字钟硬件中时钟模块、和相关控制模块等的模块话设计与制作;软件同样采用模块话的设计,包括中断模块、时间调整模块设计,并采用简单流通性强的C语言编写实现。本设计实现了用LCD1602显示器显示年、月、日、星期、时、分、秒的显示功能以及跑表功能。

关键词 ATS52单片机/数字钟/LCD1602/DS1302时钟芯片

目录

第一章 工程训练目的、要求概述 ................................................................................... 3

1

1.1 基本目的 ......................................................................................................................... 3 1.2 基本要求 ......................................................................................................................... 3

第二章 设计方案的选择和确定..................................................................................................... 4

2.1、单片机选择与论证 ....................................................................................................... 4 2.2、时钟实现的选择与论证 ............................................................................................... 4 2.3、显示的选择与论证 ....................................................................................................... 4 第三章 系统硬件设计 ................................................................................................. 5 3.1器件选型 .......................................................................................................................... 5 3.2器件介绍 .......................................................................................................................... 5 3.2.1 单片机ATS52 ..................................................................................................... 5 3.2.2 LCD1602显示模块 ................................................................................................ 6 3.2.3 时钟芯片DS1302 .................................................................................................. 6 第四章 系统的软件设 ................................................................................................... 8 4.1、proteus仿真图 ............................................................................................................. 8 4.2、设计流程图 ................................................................................................................... 8 第五章 PCB板的制作与元器件的安装 ....................................................................... 11 5.1、PCB板的制作流程介绍 .............................................................................................. 11 5.2、protel原理图 .............................................................................................................. 11 5.3、生成PCB图及制板 ..................................................................................................... 11 5.4、安装元器件 ................................................................................................................. 11 第六章 性能测试、故障分析及作品展示 ................................................................... 12 6.1、故障分析 ..................................................................................................................... 12 6.2、作品展示 ..................................................................................................................... 12 第七章 心得体会 ........................................................................................................ 13 附录1:工程训练成绩评定表 ....................................................................................... 14 附录2:时钟设计程序 .................................................................................................. 15

第一章 工程训练目的、要求概述

1.1 基本目的

此次工程训练选择使用52系列单片机来制作日历时钟。学生通过实训了解相关芯片的

2

基本结构、工作原理、特性和参数以及由它们构成的日历时钟的工作原理、原理图的设计和参数的计算、元器件的选用、计算机软件实现硬件的仿真、PCB板的设计、电路的安装和调试,最后完成达到技术指标要求的标准产品。 1.2基本要求

1、依据性能指标和器件状况,设计日历时钟电子电路,并计算器件参数确定选择器件; 2、以本工程训练为实例先学习Altium Designer基本知识,并运用其绘制日历时钟原理图和PCB图;

3、掌握电子电路板制作的全过程,实现日历时钟的制作;

4、测试日历时钟的各项性能指标,可以实现分别调整秒,分,时,年,月,日,星期。

第二章 设计方案的选择和确定

2.1、单片机选择与论证

方案一:用MSP430系列单片机控制。MSP430系列单片机具有功耗超低、处理能力强大、

3

片内外设丰富、系统工作稳定、开发环境便捷等特点。但MSP430系列单片机价格较高。

方案二:采用80C51系列单片机。Atmel公司的ATS52单片机是一种低功耗、高性能CMOS8位微控制器,它内存较大,具有 8K 在系统可编程Flash 存储器,比ATC51要多4K,它可在线编程,可在线仿真功能,且价格比较便宜。本系统功能比较简单,用ATS52单片机完全可以实现。

综上所述,我们选择了第二个方案,即ATS52。 2.2、时钟实现的选择与论证

方案一:利用51单片机的定时器设计时钟,外围电路少,可以节省硬件。可是用定时器设计时钟的话,掉电或晶振的误差都会造成时间的错乱,并且,若完全用程序设计时钟还会占用大量的系统资源,从而严重影响系统的其他功能。

方案二:使用时钟芯片设计时钟,采用DS1302是美国Dallas公司生产的,将实时时钟/日历和31字节的静态RAM集成于一体的专用芯片。实时时钟/日历提供秒、分、时、日、周、月等信息。对于小于31天的月和月末的日期自动进行调整,还包括闰年校正的功能。价格也比较便宜。

综上所述,我们选择了第二种方案,即使用时钟芯片DS1302。 2.3、显示的选择与论证

方案一:采用LCD128显示,带中文字库的128X是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×, 内置8192个16*16点汉字,和128个16*8点ASCII字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4行16×16点阵的汉字. 也可完成图形显示.低电压低功耗是其又一显著特点。但128价格偏高,会增加系统造价负担。

方案二:采用LCD1602显示,LCD1602内置192种字符(160个5*7点阵字符和32跟5*10点阵字符),具有个字节的自定义字符RAM,可自定义8个5*8点阵字符或四个5*11点阵字符。其价格远比LCD128便宜,且其功能以满足本系统需求。

综上所述,我们选择了第二种方案,即使用采LCD1602。

第三章 系统硬件设计

3.1器件选型

Atmel公司的ATS52单片机是一种低功耗、高性能的特点。ATS52比ATC51要多

4

4K内存,它可在线编程,可在线仿真功能,且价格比较便宜,所以本设计选取主控MCU为Atmel公司的ATS52。

LCD1602内置192种字符,具有个字节的自定义字符RAM,可自定义8个5*8点阵字符或四个5*11点阵字符。其价格远比LCD128便宜,所以显示器件选择市面上常见的字符型液晶显示模块LCD1602。

DS1302是美国Dallas公司生产的,将实时时钟/日历和31字节的静态RAM集成于一体的专用芯片。实时时钟/日历提供秒、分、时、日、周、月等信息。对于小于31天的月和月末的日期自动进行调整,还包括闰年校正的功能。价格也比较便宜。所以选用DS1302时钟芯片。 3.2器件介绍 3.2.1单片机ATS52

一、功能特性描述

ATS52是一种低功耗、高性能CMOS 8位微控制器,具有8K 在系统可编程Flash存储器。使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得ATS52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。

二、外部引脚图

图3-1为单片机ATS52的引脚图。

图3-1 ATS52引脚图

3.2.2 LCD1602显示模块

一、LCD1602概述

字符型型液晶是一种用5×7点阵图形来显示字符的液晶显示器,根据显示的容量可以

5

分为1行16个字、2行16个字、2行20个字等,最常用的为2行16个字。本设计所采用的LCD1602即为最常用的2行16个字。

下面是HY1602A液晶模块的一些主要技术参数: 1、逻辑工作电压(VDD):+4.5~+5.5V 2、LCD驱动电压(VDD-VL):+4.5~+13.0V

3、工作温度(Ta):0~60℃(常温)/-20~75℃(宽温) 4、工作电流:<2.0mA 二、引脚图及功能介绍

本设计使用带背光的液晶模块1602采用标准的16脚接口,如图3-2,其引脚功能如下:

图3-2 LCD1602引脚图

第1脚:VSS为电源地,接GND。 第2脚:VDD接5V正电源。

第3脚:VEE为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。 第5脚:RW为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据。

第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。 第7~14脚:D0~D7为8位双向数据线。

第15脚:BLA背光电源正极(+5V)输入引脚(本图未显示)。 第16脚:BLK背光电源负极,接GND(本图未显示)。 3.2.3时钟芯片DS1302

一、功能特性描述

DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天

6

时可以自动调整,且具有闰年补偿功能。工作电压宽达2.5~5.5V。采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。

二、引脚图及功能介绍 如图3-3为DS1302引脚图:

图3-3 DS1302引脚图

各引脚的功能为:

X1 、X2: 32.768KHz 晶振管脚 GND:接地 RST:复位脚

I/O :数据输入/输出引脚 SCLK:串行时钟

Vcc1、Vcc2 :电源供电管脚 DS1302有下列几组寄存器:

DS1302有关日历、时间的寄存器共有12个,其中有7个寄存器(读时81h~8Dh,写时80h~8Ch),存放的数据格式为BCD码形式,如图所示。

第四章 系统的软件设计

7

4.1、proteus仿真图

图4-1 proteus仿真图

仿真时,液晶显示屏会先出现姓名、学号。然后跳转到时钟界面,准确显示时间并跳时。当按下与R2串联的按键时,时钟复位;当按下与单片机十二脚串联的按键时,时钟进入设置模式;在设置模式下,按下与单片机十三脚串联的按键时,实现数字加一功能;在设置模式下,按下与单片机十四脚串联的按键时,实现数字减一功能; 4.2、设计流程图

图4-2 主程序流程图

主程序流程图对时钟的时间的进位、设定时间进行了设计。要想完成上述功能必须先进行中断操作,然后操作规定按键实行调时。

8

定时中断 重装定时常数 加100ms 整秒 调整秒单位 整分 调整分单位 整时 调整时单位 整日 调整日单位 整月 月判断 调整月单位 整年 调整年单位

图4-3 定时中断程序流程图

定时中断程序流程图,是在主程序进行完中断操作后,对时间进行判断,当满足相邻两时间单位的进位条件时,实行仅为工作,达到准确走时的目的。

9

中断开始 按键选择 按SB3 进入2路调进按SB1 按SB3 进入3路调 年单元按SB2 单元加1 按SB2 月单元 按SB1 按SB3 调整年单元 按SB1 按SB3 调整月单元 日单元 单元加1 按SB2 单元加1 按SB3 按SB2 时单元 按SB1 调整日单元 按SB1 按SB3 调整时单元 分单元 单元加1 按SB2 单元加1 按SB3 按SB2 开 关定时 按SB3 按SB2 按SB1 调整分单元 按SB1 调整秒单元 按SB1 中断返回

图4-4 调时功能流程图

调时程序流程图,是在按下设置键主程序进入中断后,按照事先设定好的按键进行加一、减一操作,从而达到时间调整的功能。

10

第五章 PCB板的制作与元器件的安装

5.1、 PCB板的制作流程介绍

PCB板制作的一般流程:

设计绘制原理图→导成PCB图→打印输出(热转印纸) ↓

金属焊盘钻孔← 腐蚀(留下电子线路)← 利用热转印法将PCB图转到敷铜板 ↓

焊接安装元器件→ 调试→ 成品 5.2、protel原理图

图5-1 单片机时钟电路protel原理图

5.3生成PCB图及制板

图5-2 单片机时钟电路PCB图

打印PCB图,热转印,腐蚀,钻孔,完成PCB板的制作。 5.4、 安装元器件

利用烙铁焊锡焊接,对照原理图或PCB图焊接安装元器件(焊接要牢固不要有虚焊点)。

11

第六章 性能测试、故障分析及作品展示

6.1、故障分析

故障一:LCD1602只有单排显示,并且用力压液晶显示器时会偶尔出现两排显示 分析:可能液晶排阵虚焊,也有可能也单片机的连接出现了断路

解决方法:首先用万用表测量了线路,在未发现与单片机断路的情况下更加确定液晶排针的虚焊可能性更大。于是重新焊接了排针,通电故障解决。

故障二:解决故障一后,开启时钟只出现了显示姓名学号,年月日、时间显示全为“85”数字。同时时钟芯片DS1302有发烫现象。

分析:DS1302时钟芯片未工作,可能时钟芯片晶振与DS1302未连接好或者焊接时短路。 解决方法:检查分析状况下的问题都没有出现的情况下,对照原理图发现DS1302封装错误,变成了镜像,于是把DS1302芯片焊接到覆铜面。重新调试,单片机时钟按要求工作。 6.2、作品展示

图6-1 实物展示

第七章 心得体会

1、通过本次实验,因为之前接触到的电子系统设计不多,所以一开始,感觉难以入手,就算上网载了很多程序,也看不懂。后来请求同学的帮助,了解了要对各种芯片编写程序时首先应找到该芯片的数据手册,根据数据手册上的说明、时序要求及流程图编写对应程序。

2、其次,再次巩固了Keil C51工程文件的建立,程序编写以及编译的掌握程度。最重要的是,因为只是水平有限,要自己编写C程序很难,但在此实验中,最大的收获莫过于看懂别人的程序,分析之后,自己拼凑编写以实现

12

不同的功能。并且掌握了52C程序的编写过程。

3、掌握了Proteus的使用方法,从实际操作中认识到Proteus在仿真方面的优越性,激发了自己学习Proteus的兴趣;

4、因为自己要修改程序,所以单单花费在程序分析的时间就很多,为了更好的理解程序,我把每句主要程序的后面都注释了该语句的意思,详情可以见程序清单,发现注释语义的工作量也是非常大的。写实验报告时,每个模块的流程图都是自己画的,用WORD文档画图真的很麻烦,而且不是很美观。因为时间比较仓促,流程图写的条理性不够,不过相信以后多多练习,就可以做得更好。

5、在这次实验中我遇到了很多故障,不过通过各种渠道(比如网络,请教同学,老师等等)解决了一些故障,虽然没有全部解决,但能在短短一周内通过此次作业,实现电子钟的功能,还是有点成就感的。在解决这些问题的过程中发现网络确实是一个很好的学习平台,利用前人的经验可以提高自己的解决实际问题的能力。通过这一个多礼拜的学习实践,使我对所学的知识进行了系统的复习和巩固,在以前学习中不够清晰的概念得到了更好的理解。相信通过不断的学习,能使自己扬长补短。 参考文献

[1]余发山.单片机原理及应用技术.江苏:中国矿业大学出版社,2003. [2]王建校.51系列单片机及C51程序设计.北京:科学出版社,2002. [3]谭浩强.C程序设计.北京:清华大学出版社,2005.

[4]何立民.单片机高级教程.北京:北京航空航天大学出版社,2001.

[5]王福瑞.单片微机测控系统设计大全.北京:北京航空航天大学出版社,2003. [6]胡力刚,王养森,陈宁.单片机在液晶显示器系统中的应用.电子工程师,2005. [7] 代启化.基于Proteus的电路设计与仿真[J].现代电子技术.2006,第19期.

[8] 曹洪奎;马莹莹 基于Proteus单片机系统设计与仿真[J]. 辽宁工学院学报07年04期 [9] 侯玉宝 基于Proteus的52系列单片机设计与仿真[M]电子工业出版社,2008.270~288

附录1:

工程训练成绩评定表

专业:电气工程及其自动化班级:电气102班 学号:7022810117 姓名:张 竹 君 项目名称 基于ATS52单片机的电子时钟设计 13

设计任务与要求 1、依据性能指标和器件状况,设计日历时钟电子电路,并计算器件参数确定选择器件; 2、以本工程训练为实例先学习Altium Designer基本知识,并运用其绘制日历时钟原理图和PCB图; 3、掌握电子电路板制作的全过程,实现日历时钟的制作; 4、测试日历时钟的各项性能指标,可以实现分别调整秒,分,时,年,月,日,星期。 指导教师评语 建议成绩: 指导教师: 教研组评定意见 评定成绩: 负责人: 时间: 年 月 日 附录2:时钟设计程序

#include //包含单片机寄存器的头文件 #include //包含_nop_()函数定义的头文件 #define uchar unsigned char

uchar code tab3[]={\"zhang zhu jun\uchar code tab4[]={\"7022810117\

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

14

以下是DS1302芯片的操作程序

************************************************************************/ uchar code digit[10]={\"01234567\ //定义字符数组显示数字 sbit RST=P1^3; //位定义1302芯片的接口,复位端口定义 sbit DATA=P1^4; //位定义1302芯片的接口,数据输出端定义 sbit SCLK=P1^5; //位定义1302芯片的接口,时钟输出端口定义 char k=0,q=0,w=0,e=0,r=12,t=11,y=5,u=10; /***函数功能:延时程序******/ void delaynus(uchar n) {

unsigned char i; for(i=0;i/****函数功能:向1302写一个字节数据****/ void Write1302(uchar dat) {

uchar i;

SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备 delaynus(2); //稍微等待,使硬件做好准备 for(i=0;i<8;i++) //连续写8个二进制位数据 { DATA=dat&0x01; //取出dat的第0位数据写入1302 delaynus(2); //稍微等待,使硬件做好准备 SCLK=1; //上升沿写入数据 delaynus(2); //稍微等待,使硬件做好准备 SCLK=0; //重新拉低SCLK,形成脉冲 dat=dat>>1; //将dat的各数据位右移1位,准备写入下一个数据位 } }

/***************************************************** 函数功能:根据命令字,向1302写一个字节数据 入口参数:Cmd,储存命令字;dat

***************************************************/ void WriteSet1302(uchar Cmd,uchar dat) {

RST=0; //禁止数据传递

SCLK=0; //确保写数居前SCLK被拉低 RST=1; //启动数据传输

delaynus(2); //稍微等待,使硬件做好准备 Write1302(Cmd); //写入命令字 Write1302(dat); //写数据

SCLK=1; //将时钟电平置于已知状态 RST=0; //禁止数据传递 }

/***************************************************** 函数功能:从1302读一个字节数据

***************************************************/ uchar Read1302(void) {

uchar i,dat; delaynus(2); //稍微等待,使硬件做好准备 for(i=0;i<8;i++) //连续读8个二进制位数据 { dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位 if(DATA==1) //如果读出的数据是1 dat|=0x80; //将1取出,写在dat的最高位 SCLK=1; //将SCLK置于高电平,为下降沿读出

15

delaynus(2); //稍微等待 SCLK=0; //拉低SCLK,形成脉冲下降沿 delaynus(2); //稍微等待 }

return dat; //将读出的数据返回 }

/***************************************************** 函数功能:根据命令字,从1302读取一个字节数据 入口参数:Cmd

***************************************************/ uchar ReadSet1302(uchar Cmd) {

unsigned char dat;

RST=0; //拉低RST

SCLK=0; //确保写数居前SCLK被拉低 RST=1; //启动数据传输 Write1302(Cmd); //写入命令字 dat=Read1302(); //读出数据

SCLK=1; //将时钟电平置于已知状态 RST=0; //禁止数据传递 return dat; //将读出的数据返回 }

/***************************************************** 函数功能: 1302进行初始化设置

***************************************************/ void Init_DS1302(void) {

WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令

WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值 WriteSet1302(0x82,((51/10)<<4|(51%10))); //根据写分寄存器命令字,写入分的初始值 WriteSet1302(0x84,((15/10)<<4|(15%10))); //根据写小时寄存器命令字,写入小时的初始值 WriteSet1302(0x86,((31/10)<<4|(31%10))); //根据写日寄存器命令字,写入日的初始值 WriteSet1302(0x88,((10/10)<<4|(10%10))); //根据写月寄存器命令字,写入月的初始值 WriteSet1302(0x8a,((3/10)<<4|(3%10))); //根据写星期寄存器命令字,写入星期的初始值 WriteSet1302(0x8c,((12/10)<<4|(12%10))); //根据写年寄存器命令字,写入年的初始值 }

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

以下是对液晶模块1602的操作程序

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

sbit E=P1^0; //使能信号位,将E位定义 sbit RW=P1^1; //读写选择位,将RW位定义 sbit RS=P1^2; //寄存器选择位,将RS位定义 sbit BF=P2^7; //忙碌标志位,,将BF位定义

/***************************************************** 函数功能:延时1ms

(3j+2)*i=(3×33+2)×10=1010(ns),可以认为是1毫秒

***************************************************/ void delay1ms() {

unsigned char i,j; for(i=0;i<10;i++) for(j=0;j<33;j++)

16

; }

/***************************************************** 函数功能:延时若干毫秒 入口参数:n

***************************************************/ void delaynms(uchar n) {

unsigned char i; for(i=0;i/***************************************************** 函数功能:判断液晶模块的忙碌状态

返回值:result。result=1,忙碌;result=0,不忙

***************************************************/ bit BusyTest(void) {

bit result; RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态 RW=1;

E=1; //E=1,才允许读写 _nop_(); //空操作 _nop_(); _nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间 result=BF; //将忙碌标志电平赋给result E=0; //将E恢复低电平 return result; }

/***************************************************** 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:dictate

***************************************************/ void WriteInstruction (uchar dictate) {

while(BusyTest()==1); //如果忙就等待 RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲, // 就是让E从0到1发生正跳变,所以应先置\"0\" _nop_(); _nop_(); //空操作两个机器周期,给硬件反应时间 P2=dictate; //将数据送入P0口,即写入指令或地址 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 }

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

17

函数功能:指定字符显示的实际地址

***************************************************/ void WriteAddress(uchar x) {

WriteInstruction(x|0x80); //显示位置的确定方法规定为\"80H+地址码x\" }

/***************************************************** 函数功能:将数据(字符的标准ASCII码)写入液晶模块

***************************************************/ void WriteData(uchar y) {

while(BusyTest()==1); RS=1; //RS为高电平,RW为低电平时,可以写入数据 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲, // 就是让E从0到1发生正跳变,所以应先置\"0\" P2=y; //将数据送入P0口,即将数据写入液晶模块 _nop_(); _nop_(); _nop_();

_nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 }

/***************************************************** 函数功能:对LCD的显示模式进行初始化设置

***************************************************/ void LcdInitiate(void) {

delaynms(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间

WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口 delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x38); delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x38); //连续三次,确保初始化成功 delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x0c); //显示模式设置:显示开,无光标,光标不闪烁 delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x06); //显示模式设置:光标右移,字符不移 delaynms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除 delaynms(5); //延时5ms ,给硬件一点反应时间 }

/************************************************************** 以下是1302数据的显示程序

**************************************************************/ /***************************************************** 函数功能:显示秒

18

***************************************************/ void DisplaySecond(uchar x) {

unsigned char i,j; //j,k,l分别储存温度的百位、十位和个位 i=x/10;//取十位 j=x%10;//取个位 WriteAddress(0x49); //写显示地址,将在第2行第7列开始显示 WriteData(digit[i]); //将百位数字的字符常量写入LCD WriteData(digit[j]); //将十位数字的字符常量写入LCD delaynms(40); //延时1ms给硬件一点反应时间 }

/***************************************************** 函数功能:显示分钟

***************************************************/ void DisplayMinute(uchar x) {

uchar i,j; //j,k,l分别储存温度的百位、十位和个位 i=x/10;//取十位 j=x%10;//取个位 WriteAddress(0x46); //写显示地址,将在第2行第7列开始显示 WriteData(digit[i]); //将百位数字的字符常量写入LCD WriteData(digit[j]); //将十位数字的字符常量写入LCD delaynms(40); //延时1ms给硬件一点反应时间 }

/***************************************************** 函数功能:显示小时

***************************************************/ void DisplayHour(uchar x) {

uchar i,j; //j,k,l分别储存温度的百位、十位和个位 i=x/10;//取十位 j=x%10;//取个位 WriteAddress(0x43); //写显示地址,将在第2行第7列开始显示 WriteData(digit[i]); //将百位数字的字符常量写入LCD WriteData(digit[j]); //将十位数字的字符常量写入LCD delaynms(40); //延时1ms给硬件一点反应时间 }

/***************************************************** 函数功能:显示日

***************************************************/ void DisplayDay(uchar x) {

uchar i,j; //j,k,l分别储存温度的百位、十位和个位 i=x/10;//取十位 j=x%10;//取个位 WriteAddress(0x0b); //写显示地址,将在第2行第7列开始显示 WriteData(digit[i]); //将百位数字的字符常量写入LCD WriteData(digit[j]); //将十位数字的字符常量写入LCD delaynms(40); //延时1ms给硬件一点反应时间 }

/***************************************************** 函数功能:显示月

***************************************************/ void DisplayMonth(uchar x) {

uchar i,j; //j,k,l分别储存温度的百位、十位和个位 i=x/10;//取十位

19

j=x%10;//取个位 WriteAddress(0x08); //写显示地址,将在第2行第7列开始显示 WriteData(digit[i]); //将百位数字的字符常量写入LCD WriteData(digit[j]); //将十位数字的字符常量写入LCD delaynms(40); //延时1ms给硬件一点反应时间 }

/***************************************************** 函数功能:显示星期

***************************************************/ void DisplayWeek(uchar x) {

uchar i,j; //j,k,l分别储存温度的百位、十位和个位 i=x/10;//取十位 j=x%10;//取个位 WriteAddress(0x0e); //写显示地址,将在第2行第7列开始显示 WriteData(digit[i]); //将百位数字的字符常量写入LCD WriteData(digit[j]); //将十位数字的字符常量写入LCD delaynms(40); //延时1ms给硬件一点反应时间 }

/***************************************************** 函数功能:显示年

***************************************************/ void DisplayYear(uchar x) {

uchar i,j; //j,k,l分别储存温度的百位、十位和个位 i=x/10;//取十位 j=x%10;//取个位 WriteAddress(0x05); //写显示地址,将在第2行第7列开始显示 WriteData(digit[i]); //将百位数字的字符常量写入LCD WriteData(digit[j]); //将十位数字的字符常量写入LCD delaynms(40); //延时1ms给硬件一点反应时间 }

/*************************************** 以下是对按键设置操作程序

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

/********************************************** 函数功能:显示工作模式

***************************************************/ void DisplayMode() {

if(k==0) {WriteAddress(0x4c); //写显示地址,将在第2行第7列开始显示 WriteData(' '); //将百位数字的字符常量写入LCD WriteAddress(0x4d); WriteData(' '); //将十位数字的字符常量写入LCD WriteAddress(0x4e); WriteData(' '); WriteAddress(0x4f); WriteData(' '); delaynms(50);} //延时1ms给硬件一点反应时间

if(k==1) {WriteAddress(0x4c); //写显示地址,将在第2行第7列开始显示

20

WriteData('S'); //将百位数字的字符常量写入LCD WriteAddress(0x4d); WriteData('e'); //将十位数字的字符常量写入LCD WriteAddress(0x4e); WriteData('c'); WriteAddress(0x4f); WriteData(' '); delaynms(50);} //延时1ms给硬件一点反应时间

if(k==2) {WriteAddress(0x4c); //写显示地址,将在第2行第7列开始显示 WriteData('M'); //将百位数字的字符常量写入LCD WriteAddress(0x4d); WriteData('i'); //将十位数字的字符常量写入LCD WriteAddress(0x4e); WriteData('n'); WriteAddress(0x4f); WriteData(' '); delaynms(50);} //延时1ms给硬件一点反应时间

if(k==3) {WriteAddress(0x4c); //写显示地址,将在第2行第7列开始显示 WriteData('H'); //将百位数字的字符常量写入LCD WriteAddress(0x4d); WriteData('o'); //将十位数字的字符常量写入LCD WriteAddress(0x4e); WriteData('u'); WriteAddress(0x4f); WriteData('r'); delaynms(50);} //延时1ms给硬件一点反应时间

if(k==4) {WriteAddress(0x4c); //写显示地址,将在第2行第7列开始显示 WriteData('D'); //将百位数字的字符常量写入LCD WriteAddress(0x4d); WriteData('a'); //将十位数字的字符常量写入LCD WriteAddress(0x4e); WriteData('y'); WriteAddress(0x4f); WriteData(' '); delaynms(50);} //延时1ms给硬件一点反应时间

if(k==5) {WriteAddress(0x4c); //写显示地址,将在第2行第7列开始显示 WriteData('M'); //将百位数字的字符常量写入LCD WriteAddress(0x4d); WriteData('o'); //将十位数字的字符常量写入LCD WriteAddress(0x4e); WriteData('n'); WriteAddress(0x4f); WriteData(' '); delaynms(50);} //延时1ms给硬件一点反应时间

if(k==6) {WriteAddress(0x4c); //写显示地址,将在第2行第7列开始显示 WriteData('W'); //将百位数字的字符常量写入LCD WriteAddress(0x4d); WriteData('e'); //将十位数字的字符常量写入LCD

21

WriteAddress(0x4e); WriteData('e'); WriteAddress(0x4f); WriteData('k'); delaynms(50);} //延时1ms给硬件一点反应时间

if(k==7) {WriteAddress(0x4c); //写显示地址,将在第2行第7列开始显示 WriteData('Y'); //将百位数字的字符常量写入LCD WriteAddress(0x4d); WriteData('e'); //将十位数字的字符常量写入LCD WriteAddress(0x4e); WriteData('a'); WriteAddress(0x4f); WriteData('r'); delaynms(50);} //延时1ms给硬件一点反应时间 }

/**********时间设置函数***********

**************************************/ void Timeset1() {

if(q==60) q=0; if(q==-1) q=59;

WriteSet1302(0x80,((q/10)<<4|(q%10))); }

void Timeset2() {

if(w==60) w=0; if(w==-1) w=59;

WriteSet1302(0x82,((w/10)<<4|(w%10))); }

void Timeset3() {

if(e==24) e=0; if(e==-1) e=23;

WriteSet1302(0x84,((e/10)<<4|(e%10))); }

void Timeset4() {

if(r==32) r=0; if(r==0) r=31;

WriteSet1302(0x86,((r/10)<<4|(r%10))); }

void Timeset5() {

if(t==13) t=1;

22

if(t==0) t=12;

WriteSet1302(0x88,((t/10)<<4|(t%10))); }

void Timeset6() {

if(y==8) y=1; if(y==0) y=7;

WriteSet1302(0x8a,((y/10)<<4|(y%10))); }

void Timeset7() {

if(u==70) u=0; if(u==-1) u=69;

WriteSet1302(0x8c,((u/10)<<4|(u%10))); }

/**************************************** 按键选择功能

*****************************************/ sbit TAB=P3^2; sbit ADD=P3^3; sbit DEC=P3^4;

void ButtonSelect() {

if(TAB==0) { k++; if(k==8) k=0; }

if(ADD==0&&k==1) { q++; Timeset1(); } if(DEC==0&&k==1) { q--;

Timeset1(); } if(ADD==0&&k==2) { w++; Timeset2(); } if(DEC==0&&k==2) { w--;

Timeset2(); }

23

if(ADD==0&&k==3) { e++; Timeset3(); } if(DEC==0&&k==3) { e--;

Timeset3(); } if(ADD==0&&k==4) { r++; Timeset4(); } if(DEC==0&&k==4) { r--;

Timeset4(); } if(ADD==0&&k==5) { t++; Timeset5(); } if(DEC==0&&k==5) { t--;

Timeset5(); } if(ADD==0&&k==6) { y++; Timeset6(); } if(DEC==0&&k==6) { y--;

Timeset6(); } if(ADD==0&&k==7) { u++; Timeset7(); } if(DEC==0&&k==7) { u--;

Timeset7(); } }

/***************************************************** 函数功能:主函数

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

void main(void) {

24

uchar second,minute,hour,day,month,week,year,k; //分别储存秒、分、小时,日,月,年

uchar ReadValue; //储存从1302读取的数据 LcdInitiate(); //将液晶初始化 WriteAddress(0x01); //写Date的显示地址,将在第1行第2列开始显示 for(k=0;k<14;k++)WriteData(tab3[k]),delaynms(100); //将字符常量写入LCD WriteAddress(0x43); //写Date的显示地址,将在第1行第2列开始显示 for(k=0;k<10;k++)WriteData(tab4[k]),delaynms(100); //将字符常量写入LCD delaynms(200); delaynms(200); delaynms(200); WriteInstruction (0x01); WriteAddress(0x00); //写Date的显示地址,将在第1行第2列开始显示 WriteData('D'); //将字符常量写入LCD WriteAddress(0x01); //写Date的显示地址, WriteData('T'); //将字符常量写入LCD WriteAddress(0x03); //写年月分隔符的显示地址 WriteData('2'); //将字符常量写入LCD WriteAddress(0x04); //写Date的显示地址, WriteData('0'); //将字符常量写入LCD WriteAddress(0x07); //写年月分隔符的显示地址, 显示在第1行第9列 WriteData('-'); //将字符常量写入LCD WriteAddress(0x0a); //写月日分隔符的显示地址, 显示在第1行第12列 WriteData('-'); //将字符常量写入LCD WriteAddress(0x40); //写月日分隔符的显示地址 WriteData('T'); //将字符常量写入LCD WriteAddress(0x41); //写月日分隔符的显示地址 WriteData('M'); //将字符常量写入LCD WriteAddress(0x45); //写小时与分钟分隔符的显示地址, 显示在第2行第6列 WriteData(':'); //将字符常量写入LCD WriteAddress(0x48); //写分钟与秒分隔符的显示地址, 显示在第2行第9列 WriteData(':'); //将字符常量写入LCD

Init_DS1302(); //将1302初始化 while(1) { ReadValue = ReadSet1302(0x81); //从秒寄存器读数据

second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//将读出数据转化 DisplaySecond(second); //显示秒 ReadValue = ReadSet1302(0x83); //从分寄存器读

minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayMinute(minute); //显示分

ReadValue = ReadSet1302(0x85); //从分寄存器读

hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayHour(hour); //显示小时 ReadValue = ReadSet1302(0x87); //从分寄存器读

day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayDay(day); //显示日 ReadValue = ReadSet1302(0x); //从分寄存器读

month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayMonth(month); //显示月 ReadValue = ReadSet1302(0x8b); //从分寄存器读 week=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayWeek(week); //显示星期 ReadValue = ReadSet1302(0x8d); //从分寄存器读

25

year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 DisplayYear(year); //显示年 DisplayMode() ; ButtonSelect(); } }

.

26

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- fenyunshixun.cn 版权所有 湘ICP备2023022495号-9

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务