单片机电子钟

更新时间:2024-05-21 05:44:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

滨江学院

毕业论文(设计)

题 目

学生姓名 学 号 院 系 专 业 指导教师 职 称

1

目 录

第一章 概述 .............................................. 4 1.1 背景 .............................................. 4 1.2 研究目的 .......................................... 4 第二章 设计要求与方案论证 ................................ 4 2.1 设计要求 .......................................... 5 2.2 系统基本方案选择与论证 ............................ 5 2.2.1 单片机芯片的选择与论证 ....................... 5 2.2.2 显示模块选择和论证 ........................... 5 2.2.3 时钟芯片的选择和论证 ......................... 5 2.3 电路实际最终方案决定 .............................. 6 第三章 主要原件介绍 ...................................... 6 3.1 STC89C52介绍 ..................................... 6 3.1.1 STC89C52主要功能 ............................ 6 3.1.2 STC89C52引脚介绍 ............................ 7 3.1.3 STC89C52的PDIP封装图 ........................ 7 3.2DS1302时钟芯片介绍 ................................ 8 3.2.1DS1302 简介: ................................. 8 3.2.2 DS1302引脚介绍 .............................. 9 3.2.3 DS1302读写时序说明.......................... 9 3.3 MT05643DR数码管介绍 ............................. 10 3.4 语音芯片介绍 ..................................... 11 第四章 系统硬件设计 ..................................... 12

2

4.1 电路设计框架 ..................................... 12 4.2 STC89C52最小系统 ................................ 12 4.3 按键控制电路 ..................................... 13 4.4 DS1302时钟模块 .................................. 14 4.5 电路仿真图 ....................................... 14 第五章 系统的软件设计 ................................... 15 5.1 系统软件设计流程图 ............................... 15 5.3 对DS1302读写操作函数 ............................ 16 5.6 按键函数 ......................................... 17 设计总结 ................................................ 21 参考文献 ................................................ 21 致 谢 .................................................. 22 Abstract ................................................ 23 附录 .................................................... 24 附录一源程序代码 ........................................ 25 附录二原件清单 .......................................... 31

3

基于STC89C52的可调电子钟设计

摘要:随着单片机技术飞速发展,它有力的推动了现代电子产品性能的增加。时间就是金钱,时间就是生命,时间就是胜利,准确掌握时间并且分配时间对人们来说十分重要,时钟是我们生活中必不可少的工具之一。本设计则是利用了STC89C52单片机对 DS1302时钟芯片进行读写操作,并通过时钟数码管来显示时钟信息,这样便构成了一个单片机电子时钟。 关键词:单片机,电子时钟,STC89C52

第一章 概述

1.1 背景

近年来伴随着计算机在社会上的应用以及大规模集成电路应用的发展,单片机的应用正不断的深入,由于单片机具有、体积小、功能强、价格便宜、功耗低、使用方便等特点,所以特别适合与控制有关的系统,越来越广泛的自动控制,智能化的仪器,仪表,数据采集,军工产品和家用电气的各个领域。单片机往往是作为一个核心部件来使用的,再根据其具体硬件结构以及针对具体应用对象特点的软件结合,加以完善。

时间对于人们来说是非常宝贵的,准备掌握和分配时间对人们来说更是至关重要。随着时代推进和科学技术的不断发展,人们对时间计量的精确度越来越高,时间计量的应用也越来越广泛,这就促使了人们不断的设计和研发出新时钟。

时钟电路在计算机系统中起着至关重要的作用,它是保证系统正常工作的基础。在单片机的应用系统中,时钟有两个方面的含义:一是指为保证系统正常工作的基准振荡定时信号,主要是由晶振以及外围电路组成,晶振频率大小决定了单片机系统工作速度的快慢;二是指系统标准定时时钟,即定时时间,它通常具有两种实现方法:一种是利用软件实现,即利用单片机内部可编程定时器或者计数器来实现;另一种是用专门的时钟芯片来实现。

1.2 研究目的

本设计通过利用STC89C52单片机,DS1302芯片,外围按键和时钟数码管等部件,设计一个基于单片机的可调电子时钟。设计的电子钟通过数码管现实,能通过按键对时间进行设置,并且有报时的功能。

第二章 设计要求与方案论证

4

2.1 设计要求

⑴具有时、分、秒的显示功能 ⑵具备时、分、秒的校准功能 ⑶具有语音报时功能

2.2 系统基本方案选择与论证

2.2.1 单片机芯片的选择与论证

方案一 :

采用STC89C52芯片作为硬件核心。STC89C52的内部具有8KB ROM存储空间,512字节数据存储空间,带有2K字节EEPROM存储空间,可与MCS-51系列的单片机完全兼容,并且它可以通过串口下载。 方案二:

采用AT89S52芯片。AT89S52的内部具有8K字节程序存储空间,256字节的数据存储空间,其没有EEPROM存储空间,也可与MCS-51系列单片机完全兼容,具有在线编程可擦除技术。 两种单片机都能够完全满足设计的需要,但是STC89C52抗干扰能力强,并且价格相对比较便宜。因此选择STC89C52芯片。

2.2.2 显示模块选择和论证

方案一 :

采用点阵式数码管来现实。点阵式数码管是由八行八列的发光二极管组成,可用来显示数据。 方案二:

采用MT05643DR 四位数码管显示。

两种显示模块都能满足设计需要,但是点阵式数码管体积比较大,并且价格也相对较高,从便携实用以及成本因素考虑,采用MT05643D数码管显示。

2.2.3 时钟芯片的选择和论证

方案一:

采用单片机定时计数器提供秒信号,试用程序实现时、分、秒的计数。采用这种方案虽然能减少芯片的使用,能够节约成本,但是实现的时间误差会较大。 方案二:

采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能时钟芯片,可自动对时分秒来进行计算,并且其精确度高。因此选择DS1302时钟芯片实现时钟。

5

2.3 电路实际最终方案决定

采用STC89C52单片机作为主控制系统,采用DS1302作为时钟芯片;采用MT05643DR数码管作为显示器件。

第三章 主要原件介绍

3.1 STC89C52介绍

3.1.1 STC89C52主要功能

STC89C52是一种带8K字节 闪烁可编程 可檫除 只读存储器(FPEROM-Flash Programable and Erasable Read Only Memory )的低电压,高性能COMOS8的微处理器,俗称单片机。该器件是采用ATMEL高密度非易失存储器的制造技术制造,其与工业标准的MCS-51指令集和输出管脚相兼容。STC89C5的内部具有一个用来构成振荡器的高增益反相放大器,其引脚RXD和TXD分别是该放大器输入端以及输出端。时钟可以通过内部方式或者外部方式产生。内部方式产生的时钟电路在RXD和TXD引脚外接定时元件时,内部振荡器就会产生自激振荡。定时元件常采用石英晶体及由电容组成的并联谐振回路。晶体振荡的频率可在1.2~12MHz之间选择,电容值可以在5~30pF间选择,电容值大小可以对频率起微调作用。

外部方式产生的时钟电路RXD接地,而TXD则接外部振荡器。对 外部振荡信号没有特殊要求,仅仅要求保证脉冲的宽度,通常采用其频率低于12MHz的方波信号。片内时钟发生器可把振荡频率两分频,产生一个两相时钟P1和P2,供给单片机使用。

STC89C52主要功能如表3.1所示

表3.1 STC89C52主要功能

主要功能特性

6

兼容MCS51指令系统 32个双向I/O口 3个16位可编程定时/计数器中断 2个串行中断 2个外部中断源 2个读写中断口线 低功耗空闲和掉电模式

8K可反复擦写Flash ROM 256x8bit内部RAM 时钟频率0-24MHz 可编程UART串行通道 共6个中断源 3级加密位 软件设置睡眠和唤醒功能 3.1.2 STC89C52的引脚介绍

(1) 主电源引脚(2根)

VCC (Pin40):电源的输入,接+5V电源; GND (Pin20):接地线; (2)外接晶振引脚(2根)

XTAL1 (Pin19):片内振荡电路输入端; XTAL2 (Pin20):片内振荡电路输出端; (3)控制引脚(4根)

RST/VPP (Pin9):复位引脚。引脚上,出现2个机器周期高电平将使单片机复位; ALE/PROG (Pin30):地址锁存允许信号; PSEN (Pin29):外部存储器读选通信号;

EA/VPP (Pin31):程序存储器的内外部选通,接低电平从外部程序的存储器读指令,如果接高电平则是从内部程序的存储器读指令。 (4)可编程输入/输出引脚(32根)

STC89C52单片机有4组8位的可编程I/O口,其分别位P0、P1、P2、P3口,每个口有8位(8根引脚),一共32根。

PO口(Pin39~Pin32):8位双向I/O口线,名称为P0.0~P0.7; P1口(Pin1~Pin8):8位准双向I/O口线,名称为P1.0~P1.7 ; P2口(Pin21~Pin28):8位准双向I/O口线,名称为P2.0~P2.7 ; P3口(Pin10~Pin17):8位准双向I/O口线,名称为P3.0~P3.7;

3.1.3 STC89C52的PDIP封装图

STC89C52的PDIP封装图如图3.1:

7

图3.1 STC89C52的PDIP封装图

3.2 DS1302时钟芯片介绍

3.2.1 DS1302 简介:

DS1302是由美国的DALLAS公司推出的一种高性能低功耗的实时时钟芯片,附加31字节静态RAM,采用了SPI三线接口和CPU进行同步通信,并且可采用突发方式 一次传送多个字节时钟信号以及RAM数据。实时时钟可以提供时分秒年月日以及星期,一个月小于31天可以自动进行调整,并且具有闰年的补偿功能。工作电压则宽达2.5~5.5V。其采用双电源的供电(主电源和备用电源),可以设置备用电源的充电方式,提供对后背电源进行涓细电流充电的能力。 DS1302用于数据的记录,尤其是对某些具有特殊意义的数据点的记录,能实现数据与出现此数据的时间同时记录,因此广泛的应用于测量系统中。

DS1302 时钟芯片存在时钟精度不高,易受环境影响,出现时钟混乱等一些缺点。DS1302可以用于数据的记录,特别是对具有特殊意义数据点的记录,能够实现数据和出现此数据时间同时的记录。这种记录对长时间连续测控系统结果的分析和对异常数据出现原因的查找具有重要的意义。传统数据记录方式分别是隔时采样或是定时采样,没有具体的时间记录,因此,只能记录数据却不能准确的记录出现的时间。如果采用单片机计时,一方面需要采用计数器,占用了硬件资源,而另一方面则需要设置中断、查询等,同样耗费了单片机资源。并且某些测控系统会不允许。但如果在系统中采用时钟芯片DS1302,则可以很好地解决这个问题。

DS1302的工作原理:

DS1302工作时为了能对任何数据传送进行初始化,需要将复位脚(RST)置为高电平并且将8位地址以及命令信息装入移位的寄存器。数据在时钟(SCLK)上升沿串行输入,前8位指定访问地址,命令字装入移位的寄存器后,在之后的时钟周期中,读写操作时分别输入数据和输出数据。时钟脉冲的个数在单字节的方式下是8+8(8位地址+8位数据),在多字节的方式下是8加最多可达248的数据。 DS1302寄存器以及控制命令:

8

对 DS1302的操作就是对它内部寄存器的操作,DS1302内部一共具有12个寄存器,其中有七个寄存器与日历和时钟相关,存放的数据位是BCD码形式。另外,DS1302还有年份寄存器、充电寄存器、控制寄存器、时钟突发寄存器以及与 RAM 相关的寄存器等。时钟突发寄存器可以一次性顺序读写除充电寄存器以外的寄存器。

3.2.2 DS1302引脚介绍

DS1302外部引脚分配如图3.3

图3.3 DSI302外部引脚分配

各个引脚的功能为:

Vcc1:是备用电源;Vcc2是主电源。当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2< Vcc1时,则是由Vcc1向DS1302供电。 SCLK:串行时钟输入; I/O:三线接口时双向数据线;

CE:输入信号,在读、写数据时,必须为高。此引脚具有两个功能:一CE开始控制字访问移位寄存器的控制逻辑;其次CE提供结束单字节或者多字节数据传输的方法。

3.2.3 DS1302读写时序说明

DS1302是SPI总线的驱动方式。它不仅需要向寄存器写入控制字还需要读取相应寄的存器的数据。

要与DS1302通信,需要了解DS1302的控制字。DS1302的控制字如图3.4。

图3.4DS1302的控制字

控制字最高有效位(位7)必须是逻辑1,如果为0,就不能把数据写入到DS1302中。 位6:如果为0,表示存取日历时钟的数据,为1表示存取RAM数据; 位5至位1(A4~A0):指示操作单元地址;

位0(最低有效位):如为0,表示进行写操作,为1表示进行读操作。

9

控制字总是从最低位开始输出的。在控制字指令输入后下一个SCLK时钟的上升沿时,数据写入DS1302,数据输入从最低位(0位)开始。同样,在紧跟8位控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。数据读写时序如图3.5。

图3.5数据读写时序

3.3 MT05643DR数码管介绍

MT05643DR是一个四位共阳极数码管,四位数码管是半导体的发光器件,它的基本单元为发光二极管,能显示4个数码管叫四位数码管。数码管按段数可分为七段数码管以及八段数码管,八段数码管则比七段数码管多了一个发光二极管的单元(多一个小数点显示)。按照发光二极管单元的连接方式分为共阳极和共阴极数码管。共阳极数码管指将所有的发光二极管阳极接到一起形成公共阳极(COM)数码管。共阳极数码管应用时则是将公共极COM接到+5V,当某一字段的发光二极管阴极为低电平时,相应字段则点亮。当某一字段阴极为高电平时,相应字段则不亮。共阴极数码管是指将所有的发光二极管的阴极接到一起从而形成公共阴极(COM)的数码管。共阴极数码管在应用时应将公共极COM接到地线GND上,当某一字段的发光二极管的阳极为高电平时,相应字段就点亮。当某一字段的阳极为低电平时,相应字段则不亮。

数码管的动态显示接口是单片机中应用最为广泛的显示方式之一,动态驱动是将所有数码管的8个显示笔划\的同名端连在一起,另外为每个数码管公共极COM增加位选通控制电路,位选通是由各自独立的I/O线控制。当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是哪一个数码管会显示出字形,取决于单片机所对位选通COM端电路的控制,所以只要将需要显示的数码管的选通控制打开,该位就能显示出字形,没有选通的数码管就不会亮。通过时分轮流控制各个数码管的COM端,就使各个数码管轮流受控显示,这就是动态驱动。在轮流显示的过程中,每位数码管点亮时间为1-2ms,由于人的视觉暂留现象以及发光二极管的余辉效应,尽管实际上各位数码管并不是同时点亮,但是只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能节省大量的I/O端口,并且功耗更低。MT05643DR数码管电路图如下图

10

图3.3数码管示意图

图3.4数码管内部结构

3.4 语音芯片介绍

语音芯片是将语音信号通过采样转化为数字,存储在IC的ROM中,并且再通过电路将ROM中的数字还原成语音信号。根据语音芯片的输出方式可分为两大类,一类是PWM输出方式,一类是DAC输出方式。PWM输出音量不能连续可调,不能接普通功放;而DAC经内部EQ放大,该语音芯片声音能连续可调,可以数字控制调节,可外接功放。普通语音芯片放音功能实质上是一个DAC过程,而ADC过程资料则是由电脑完成,其中包括了对语音信号的采样、压缩、EQ等处理。录音芯片则包括ADC和DAC两个过程,都是由芯片本身来完成的,包括了语音数据的采集、分析、压缩、存储、播放等步骤。音质的优劣则是取决于ADC和DAC位数的多少。例如:20秒到 340秒,最低从10秒到340秒.语音芯片直观地从名称上看,就是与语音有关的芯片,语音就是存储电子声音,凡是能发出声音的芯片就是语音芯片,俗称声音芯片;英文准确些来说应该是Voice IC。 在语音芯片中,根据声音类型的不同可分为(Speech IC)和(Music IC)两种。

单片语音录放电路是由语音存储单元、增益控制电路、输出放大器所组成的。一个最小的语音系统仅由一个喇叭、一个电源、少数电阻电容组成。利用它语音和音频信号被直接存储,在相应预设定的时间段里可以实现报时功能。

本设计采用的语音芯片的控制原理图,如图3.4.1。任何时候需要播放的那一段都是先发送一个RET信号,再发送相对应的段码就可以了,任何时候发送一个RET信号(不接着发送段落选择脉冲)都会使芯片停止工作,同时播放指针则指向第一段。

11

图3.4.1控制原理图

第四章 系统硬件设计

4.1 电路设计框架

显示模块 复位模块 主控模块 时钟模块 按键模块 语音模块

图4.1电路设计框架

4.2 STC89C52最小系统

12

最小系统指能进行正常工作的最简单的电路。STC89C52的最小应用系统电路如图3.2所示。它包含了五个电路部分:电源电路,时钟电路,复位电路,片内外程序存储选择电路以及输入/输出接口电路。其中电源电路、时钟电路和复位电路是保证单片机系统能正常工作的最基本的三部分电路。电源电路:其芯片引脚VCC一般接上直流稳压电源+5V;引脚GND接电源+5V负极,电源的电压范围在4-5.5之间,可保证单片机系统的正常工作。为了提高电路的抗干扰性,通常在引脚Vcc与GND间街上10uF的电解电容和一个0.1uF的陶片电容,这样可以抑制杂波的干扰,进而有效的保证电路的稳定性能。时钟电路:单片机的引脚18,19外接晶振以及电容,STC89C52芯片工作频率则是在2-33MHz范围之间选择,单片机工作频率由晶振XT频率所取决的。复位电路:一般在引脚RST上保持24个工作的主频周期高电平,单片机则可以完成复位,但是为了保证系统的可靠复位,复位电路应该使用引脚RST保持10ms以上的高电平。如图4.2为STC89C52的最小系统。

图4.2最小系统

4.3 按键控制电路

本设计需要校对时间,所以用三个按键来实现。通过按K1实现时分秒的切换,在任意数码管闪烁是按K2,K3分别是对该闪烁值增1和减1,在任意调节状态按K1,正常显示时间。K4则是对当时时间的报时。下图4.3为按键控制电路:

图4.3按键控制电路图

13

4.4 DS1302时钟模块

DS1302时钟模块的电路图 如图4.4

图4.4 DS1302时钟模块

4.5 电路仿真图

如图4.5

14

第五章 系统的软件设计

系统的软件设计也是对工具系统功能的设计。单片机软件设计主要包括执行软件(完成各种实质性功能)的设计以及监控软件的设计。单片机软件设计通常要考虑以下几个方面的问题:

(1)根据软件功能的要求,将系统软件划分为若干个相对独立的部分,从而设计出合理的总体结构,使软件开发清晰简洁和流程合理;

(2)需要培养良好的编程风格,比如考虑结构化程序的设计、实行模块化、子程序化。不进便于调试、链接,而且便于移植和修改;

(3)建立正确的数学模型,通过仿真提高系统性能,并且选择合适的参数; (4)绘制程序流程图; (5)合理的分配系统资源;

(6)为程序加入注释,提高程序的可读性,实施软件工程; (7)注意软件的抗干扰性的设计,提高系统可靠性。

5.1 系统软件设计流程图

主程序是先开始,然后初始化地址参数,定时器启动后进行按键检测,检测完之后就可以显示时间。DS1302时钟芯片具有通电自动计算时间的功能,采用DS13O2时钟芯片单片机时钟,实质上就是读取时钟芯片里的时钟信息并显示出来。只要时间初值正确,时钟就能够一直准确的走下去。如图5.1

15

图5.1主函数流程图

显示 将时间转换为字符型 读取时间 是否有键按下 初始化地址参数 开始 是 调用子函数修改时间

5.2 对DS1302读写操作函数

在对DS1302时钟芯片操作前,应对其操作时序有所了解,参看前文对DS1302的介绍。DS1302是采用串行方式与单片机进行通信,一个机器周期只能读写一个字节的一位,因此在单片机与DS1302芯片间传输一字节(8位)数据,要分8次进行,并且先从低位开始传输。如图5.2.1,5.2.2为写DS1302流程图,读DS1302流程图。

16

复位端变高启动一次数据传送工作 复位端变高启动一次数据传送工作 开始 开始 Y N Y N 够八次吗 够八次吗 SCLK发脉冲 SCLK发脉冲 写命令字节一位 写命令字节一位 N N Y Y

结束 结束 复位端变低 复位端变低 够八次吗 够八次吗 SCLK发脉冲 SCLK发脉冲 写数据字节一位 读数据字节一位 5.3 按键函数

此电子时钟共有4个按键,K1、K2、K3与调试有关,按键K4为报时按键

K1 功能键:在24小时显示模式下,该键被第一次按下后进入秒调整,数码管显示器上的时间停止走动。模式,再次按下后进入分调整模式,接着是时调整模式K当第四次按下该键后

17

退出。

K2 调整键:在调整模式下,该键每按下一次,相应时间K加1

K3 确定键:在调整模式下,该键被按下后,退出调整模式,并将调整后的时间写入DS1302 K4 为报时按键,按下则由语音芯片报出对应的时间。

每按下K1键,状态改变一次,标记状态从1改变到3如图5.3.1为按键状态处理工程

状态3 设置时间:时 图5.3.1按键状态处理

状态1 设置时间:秒 状态2 设置时间:分 每按一次键,相应的时间加1,但是时间是以BCD码的形式存放在DS1302时钟芯片上的,如果直接对其进行操作,如秒、假如秒的初试时间是00,它在DS1302芯片中存放的值为00000000,它的后4位则代表秒的个位,在时钟芯片自动计时的时侯,10秒后它的后四位为10时,它能自动进位变为00010000。但是在调秒的状态下按10次S2键,我们希望秒变成00010000,实际上其值变为00001010,因此我们引入参数分别代表秒的十位和个位。

设计总结

通过本次论文的设计,使我加深了对单片机知识的认识,并且熟悉了单片机系统的设计流程。本次设计功能上基本达标:时钟的显示,调时功能,语音报时功能。

技术在不断进步,机械式的时钟已经被淘汰,取而代之的是具有高度准确性、直观性、无机械装置并且具有更长的使用寿命等有点的电子时钟。电子时钟更加具有人性化,更能提高人们的生活质量,更受人们的欢迎。机械时代已经远去,电子时代已经到来,作为新时代的我们,应该提高自身能力,适应新时代的发展。

从这次的论文设计中,我真正的体会到知识的重要性,特别是要理论联系实际,把我们所学的理论和知识运用到实际生活中。

18

参考文献

[1] 杨家国.《单片机原理与应用及C51程序设计》.清华大学出版社.2009-7 [2] 周向红.《51单片机课程设计》[M] .华中科技大学出版社.2011-1 [3] 阎石.《数字电子线路》[M] .高等教育出版社.2009-7

[4] 周兴华. 《手把手教你学单片机C语言程序设计》[M].北京:北京航空航天大学出版社,2007年

[5] 张义和.《例说51单片机》[M].北京:人民邮电出版社,2010年 [6] 孙涵芳.《单片机原理及应用》[M].北京航空航天大学出版社,1996 [7] 黄正谨.《综合电子设计与实践》[M].东南大学出版社,2003 [8] 谢嘉奎.《电子线路》[M].高等教育出版社,2003

[9] Lee Jri.High-Speed Circuit Designs for Transmittersin Broad-band Data Links. IEEE Journal of Solid-State Circuits[J]. 2006

[10] Lim Kyoohyun,Park Chanhong,Kim Dalsoo,et al.A low-noise phase-locked loop design by loop bandwidth optimization. IEEE Journal of SolidState Circuits. 2000 [11] George Lee,Karina Ng,Edmond Kwang.Design of ring oscillator based voltage controlled oscillator. Project Final Report[R]. 2005

Adjustable electric clock Based on the STC89C52

Chen Peng

Nanjing University of Information Science & Technology, Binjiang college, Information Engineering Specialty ,

Nanjing 210044

Abstract

With the rapid development of microcomputer technology in it's promotion ,it further improve the performance of modern electronic products. Time is money, time is life, time is victory. Accurate grapes of time and allocation of time is crucial to people. The clock is necessary in our life tools. In this paper, through the use of STC89C52 microcontroller by DS1302 clock chips for reading and writing operation so that forming a single chip electronic clock.

Key Words: Microcontroller, STC89C52, Electronic clock.

19

附录

附录一:程序源代码

#include //包含单片机寄存器的头文件

#include

//包含_nop_()函数定义的头文件 #define uchar unsigned char #define uint unsigned int

sbit SCLK=P1^1; //位定义1302芯片的接口,时钟输出端口定义在P1.0引脚

sbit DATA=P1^0; //位定义1302芯片的接口,数据输出端定义在P1.1引脚

sbit RST=P1^2; //位定义1302芯片的接口,复位端口定义在P1.2引脚

sbit key1=P1^6; //调时 sbit key2=P1^7; //调分 启动 sbit key3=P3^0; sbit key4=P3^1;

sbit busy=P1^3;//判忙端接8脚 sbit SDA=P1^4;//信号端接7脚

sbit RST2=P1^5;//触发端接6脚

void baoshi(unsigned char z); void yuyin(); uchar

a,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp;

unsigned char m,n,p,t;

unsigned char min,hour; //开始走秒 uchar code duan_code[]={

0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳数码管段码表 uchar display_code[]={

0x00,0x00,0xbf,0x00,0x00,0xbf,0x00,0x00};//显示格式,中间两个横杠 uchar bit_code[]={

0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f };//

20

数码管位选 uchar current_time[7]; //所读取的日期和时间 //调节标志 /***************************************************** 函数功能:延时若干微秒

入口参数:n

***************************************************/ void delaynus(unsigned char n) { unsigned char i; for(i=0;i

{ uchar i; while(x--) for(i=0;i++;i<120); } /***************************************************** 函数功能:向1302写一个字节数据 入口参数:x ***************************************************/ void Write1302(unsigned char dat) { unsigned char 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>>=1; //将dat的各数据位右移1位,准备写入下一个数据位

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

**************/ void WriteSet1302(unsigned char Cmd,unsigned char dat) { RST=0; //禁止数据传递 SCLK=0; //确保写数居前SCLK被拉低 RST=1; //启动数据传输 delaynus(2); //稍微等待,使硬件做好准备 Write1302(Cmd); //写入命令字 Write1302(dat); //写数据 SCLK=1; //将时钟电平置于高电平状态 RST=0; //禁止数据传递

} /***************************************************** 函数功能:从1302读一个字节数据 入口参数:x

***************************************************/ unsigned char Read1302(void) {

21

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

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

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

函数功能:根据命令字,从1302读取一个字节数据

入口参数:Cmd

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

unsigned char ReadSet1302(unsigned char 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(0x82,(miao/10<<4)|(miao)); //根据写秒寄存器命令字,写入秒的初始值 WriteSet1302(0x84,(fen/10<<4)|(fen)); //根据写分寄存器命令字,写入分的初始值 WriteSet1302(0x80,(fen/10<<4|(fen))); WriteSet1302(0x8E,0x80); //根据写状态寄存器命令字,写入保护指令 } displaymiao() { display_code[0]=duan_code[miao/10];//小时为的十位

display_code[1]=duan_code[miao];//小时位的个位

P2=bit_code[0]; P0=display_code[0]; P2=bit_code[1]; P0=display_code[1]; } displayfen() { display_code[3]=duan_code[fen/10];//分钟位的十位

display_code[4]=duan_code[fen]; P2=bit_code[3]; P0=display_code[3];

22

delayms(5);

//分钟为的个位 //按动3次,shi //write_1602com(0x0f); P2=bit_code[4]; P0=display_code[4]; delayms(5); } displayshi() { display_code[6]=duan_code[shi/10];//秒位的十位

display_code[7]=duan_code[shi]; P2=bit_code[6]; P0=display_code[6]; delayms(5);

P2=bit_code[7]; P0=display_code[7]; delayms(5); }

void keyscan() {

if(key1==0)//---------------key1为功能键(设置键)-------------------- {

delayms(9);//延时,用于消抖动

if(key1==0)//延时后再次确认按键按下 {

delayms(20);

while(!key1); key1n++; if(key1n==4)

key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环 switch(key1n) {

case 1: TR0=0;//关闭定时器 //TR1=0;

temp=(miao)/10*16+(miao);//秒数据写入DS1302

WriteSet1302(0x8e,0x00);

WriteSet1302(0x80,0x80|temp);//miao write_1302(0x8e,0x80); break; case 2: display_code[0]=duan_code[miao/10];//小时为的十位

display_code[1]=duan_code[miao];//小时位的个位

P2=bit_code[0]; P0=display_code[0]; P2=bit_code[1]; P0=display_code[1]; delayms(5);

//write_1602com(0x0f); break; case 3: display_code[3]=duan_code[fen/10];//分钟位的十位

display_code[4]=duan_code[fen]; P2=bit_code[3]; P0=display_code[3]; delayms(5);

//分钟为的个位 //按动3次,shi //write_1602com(0x0f); P2=bit_code[4]; P0=display_code[4]; delayms(5); break;

case 4: display_code[6]=duan_code[shi/10];//秒位的十位

display_code[7]=duan_code[shi]; P2=bit_code[6]; P0=display_code[6]; delayms(5);

P2=bit_code[7]; P0=display_code[7];

23

delayms(5); //秒位的个位 break;

case 5:

TR0=1;//打开定时器

temp=(miao)/10*16+(miao); WriteSet1302(0x8e,0x00);

WriteSet1302(0x80,0x00|temp);//miao数据写入DS1302

WriteSet1302(0x8e,0x80);

break; } } }

//------------------------------加键

key2----------------------------

if(key1n!=0)//当key1按下以下。再按以下键才有效(按键次数不等于零) {

if(key2==0) //上调键 {

delayms(10); if(key2==0) {

//buzzer=0;//蜂鸣器短响一次 delayms(20); //buzzer=1; while(!key2); switch(key1n) {

case 1:miao++;//设置键按动1次,调秒 if(miao==60)

miao=0;//秒超过59,再加1,就归零 displaymiao();

temp=(miao)/10*16+(miao);//十进制转换成DS1302要求的DCB码

WriteSet1302(0x8e,0x00); //允许写,禁止写保护

WriteSet1302(0x80,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据 WriteSet1302(0x8e,0x80); //打开写保护 break;

case 2:fen++; if(fen==60) fen=0;

displayfen();

temp=(fen)/10*16+(fen);//十进制转换成DS1302要求的DCB码

WriteSet1302(0x8e,0x00);//允许写,禁止写保护

WriteSet1302(0x82,temp);//向DS1302内写分寄存器82H写入调整后的分数据 WriteSet1302(0x8e,0x80);//打开写保护 break;

case 3:shi++; if(shi==24) shi=0;

displayshi();

temp=(shi)/10*16+(shi);//十进制转换成DS1302要求的DCB码

WriteSet1302(0x8e,0x00);//允许写,禁止写保护

WriteSet1302(0x84,temp);//向DS1302内写小时寄存器84H写入调整后的小时数 WriteSet1302(0x8e,0x80);//打开写保护 break; } } }

//------------------减键key3,各句功能参照'加键'注释--------------- if(key3==0) {

delayms(10);//调延时,消抖动 if(key3==0) {

24

delayms(20);

while(!key3); switch(key1n) {

case 1:miao--; if(miao==-1)

miao=59;//秒数据减到-1时自动变成59 displaymiao();

temp=(miao)/10*16+(miao);//十进制转换成DS1302要求的DCB码

WriteSet1302(0x8e,0x00); //允许写,禁止写保护

WriteSet1302(0x80,temp); //向DS1302内写秒寄存器80H写入调整后的秒数据

WriteSet1302(0x8e,0x80); //打开写保护

break; case 2:fen--; if(fen==-1) fen=59; displayfen();

temp=(fen)/10*16+(fen);//十进制转换成DS1302要求的DCB码

WriteSet1302(0x8e,0x00);//允许写,禁止写保护 write_1302(0x82,temp);//向DS1302内写分寄存器82H写入调整后的分数据

WriteSet1302(0x8e,0x80);//打开写保护

break;

case 3:shi--; if(shi==-1) shi=23; displayshi();

temp=(shi)/10*16+(shi);//十进制转换成DS1302要求的DCB码

WriteSet1302(0x8e,0x00);//允许写,禁止写保护

WriteSet1302(0x84,temp);//向DS1302内写小时寄存器84H写入调整后的小时数 WriteSet1302(0x8e,0x80);//打开写保护 break; } } } } }

//-------------------------------

void init() //定时器、计数器设置函数 {

TMOD=0x11; //指定定时/计数器的工作方式为3

TH0=0; //定时器T0的高四位=0

TL0=0; //定时器T0的低四位=0 EA=1; //系统允许有开放的中断 ET0=1; //允许T0中断

TR0=1; //开启中断,启动定时器 EX1=1; EA=1; }

void display() { unsigned char ReadValue;

ReadValue = ReadSet1302(0x81); //从秒寄存器读数据

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

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

25

//显示分

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

current_time[2]

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

display_code[0]=duan_code[current_time[2]/10];//小时为的十位

display_code[1]=duan_code[current_time[2]];//小时位的个位

display_code[3]=duan_code[current_time[1]/10];//分钟位的十位

display_code[4]=duan_code[current_time[1]];//分钟为的个位

display_code[6]=duan_code[current_time[0]/10];//秒位的十位

display_code[7]=duan_code[current_time[0]];//秒位的个位

P2=bit_code[0]; P0=display_code[0]; delayms(5);

P2=bit_code[1]; P0=display_code[1]; delayms(5);

P2=bit_code[2]; P0=display_code[2]; delayms(5);

P2=bit_code[3]; P0=display_code[3]; delayms(5);

P2=bit_code[4]; P0=display_code[4]; delayms(5);

P2=bit_code[5]; P0=display_code[2]; delayms(5);

P2=bit_code[6]; P0=display_code[6]; delayms(5);

P2=bit_code[7]; P0=display_code[7]; delayms(5); P2=0xff; delayms(5); }

void read_clockS(void) {

// hour1=hour; hour = ReadSet1302(0x85); //读取小时数据 min = ReadSet1302(0x83); //读取分钟数据

/*在本电子钟中暂不需要读取以下信息,暂时屏蔽*/

//sec = ReadSet1302(0x81); //读取秒数据

// day = DS1302_r(0x87); //读取日数据

//month= DS1302_r(0x89); //读取月数据

//week = DS1302_r(0x8b); //读取星期数据

//year = DS1302_r(0x8d); //读取年数据 }

/*****读取时间*****/ void check_shijian(void) { read_clockS();

//将读出数据转化

//hour=((hour&0x70)>>4)*10 + (hour&0x0F); //将读出数据转化

26

//显示分 //从分寄存器读 // min=((min&0x70)>>4)*10 + (min&0x0F); //将读出数据转化 //m=hour/10; //n=hour; // p=min/10;

// t=min; //显示小时 //显示小时 //读取时间

m=(hour>>7)*8+((hour>>6)&0X01)*4+((hour>>5)&0X01)*2+((hour>>4)&0X01);//计算得到小时十位数字

n=((hour>>3)&0x01)*8+((hour>>2)&0X01)*4+((hour>>1)&0X01)*2+(hour&0X01);//计算得到小时个位数字

p=(min>>7)*8+((min>>6)&0X01)*4+((min>>5)&0X01)*2+((min>>4)&0X01); //计算得到分钟十位数字

t=((min>>3)&0x01)*8+((min>>2)&0X01)*4+((min>>1)&0X01)*2+(min&0X01);//算得到分钟个位数字 } void main(void) { init(); while(1) {

/*if(adjust_flag==0)

{ //扫描按键,当按键没有被按下时,单片机从ds1302读取时间数据 ReadValue = ReadSet1302(0x81); //从秒寄存器读数据

current_time[0]=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//将读出数据转化 //显示秒 ReadValue = ReadSet1302(0x83); //

从分寄存器读

current_time[1]

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

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

current_time[2]

=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 //显示小时 } */ keyscan(); display(); if(key4==0) {delayms(10); if(key4==0)

{ check_shijian(); yuyin();

delayms(20); } }

while(!key4); } } void timer0() interrupt 1 //取得并显示日历和时间 { unsigned char ReadValue;

ReadValue = ReadSet1302(0x81); //从秒寄存器读数据

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

27

=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 fen = current_time[1]; //显示分

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

current_time[2]

=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 void yuyin() {

busy=1;//初始化,判忙端置1,表示不忙 SDA=0;//初始化,信号端置0,表示无信号 RST2=0;//初始化,触发端置0,表示无触发

shi =current_time[2] ;

//显示温度、秒、时、分数据: }

void baoshi(unsigned char z) { //每读取一个地址的内容,先发送一个 触发信号 RST2=1; delayms(12); RST2=0; delayms(12);

while(z>0) {

SDA=1; delayms(12); SDA=0; delayms(12); z--; }

while(!busy);

delayms(12); }

baoshi(22);

if(m==0&&n==0) {

baoshi(1); }

else if(m==0&&n!=0) {

baoshi(n+1); }

else if(m==1&&n==0) {

baoshi(11); }

else if(m==1&&n!=0) {

baoshi(11); baoshi(n+1); }

else if(n!=0) {

baoshi(m+1); baoshi(11); baoshi(n+1); }

else if(n==0) {

baoshi(m+1); baoshi(11); }

baoshi(13); if(p==0&&t==0) { }

else if(p==0&&t!=0)

28

{

baoshi(p+1); baoshi(t+1); }

else if(p==1&&t==0) {

baoshi(11); }

else if(p==1&&t!=0) {

baoshi(11); baoshi(t+1); }

else if(t==0) {

baoshi(p+1); baoshi(11); }

else if(t!=0) {

baoshi(p+1); baoshi(11); baoshi(t+1); }

if(p==0&&t==0) baoshi(26); else baoshi(14);

//baoshi(23);

/* if(wm==0&&wn==0)

baoshi(1);

else if(wm==0&&wn!=0) baoshi(wn+1);

else if(wm==1&&wn==0) baoshi(11);

else if(wm==1&&wn!=0) {

baoshi(11); baoshi(wn+1); }

else if(wn!=0) {

baoshi(wm+1); baoshi(11); baoshi(wn+1); }

else if(wn==0) {

baoshi(wm+1); baoshi(11); }

if(wp!=0) {

baoshi(13); baoshi(wp+1); }

baoshi(20); */ }

附录二:元件清单

元件 型号 个数 单片机 STC89C52 1个 数码管 MT05643DR 2个 三极管 8个 29

蜂鸣器 1个 按键 4个 锁定开关 1个 5V电源插座 1个 发光二极管 1个 通用板 1块 导线和电阻 若干

30

本文来源:https://www.bwwdw.com/article/s8d7.html

Top