课程设计——DS1302数码管显示数字钟的设计1

更新时间:2024-06-18 09:46:01 阅读量: 综合文库 文档下载

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

××大学××学院××系课程设计报告

××大学××学院××系××课程设计

DS1302数码管显示数字钟的设计

学生姓名 学 号 所 在 系 专业名称 班 级 指导教师 成 绩

××大学××学院 二〇一二年六月

××大学××学院××系××课程设计报告

摘要:本课程设计要求基于STC89C52单片机实现用8位数码管进行时钟

显示。采用STC89C52单片机和DS1302实时时钟芯片,使用5V电源供电。时钟可以通过按键切换,数码管显示时、分、秒以及年、月、日,并且可以实现时钟的校准功能。包括时钟芯片驱动程序,数码管显示及驱动程序。

关键字:单片机,DS1302,时钟电路,数码管显示

Abstract: This course is designed 8 digital tube clock display

requirements based STC89C52 microcontroller. Using STC89C52 microcontroller and DS1302 real time clock chip, using a 5V power supply. Design of the clock by means of the key switches, digital tube display hours, minutes, seconds, and the year, month, day, and can achieve clock calibration function. Including the driver of the clock chip, digital display and driver.

Key words: single chip macrocomputer;DS1302;clock circuit;digital tube

display

2

××大学××学院××系××课程设计报告

目 录

1. 总体设计方案…………………………………………………………...……….1

1.1 电子钟功能介绍

1.1.1 基本功能介绍…………………………………………………………..1 1.1.2 扩展功能介绍…………………………………………………………..1 1.2 总体设计方案…………………………………………………………………1 1.2.1 计时方案……………………………………………………………..…1 1.2.2 按键方案………………………………………………………………...1 1.2.3 显示方案…………………………………………………………..…….2

2. 单元模块设计…………………………………………………………….….…...2

2.1 硬件总电路设计………………………………………………………...….…2

2.2 显示模块电路设计……………………………………………………....…….2 2.3 按键调时电路设计…………………………………………………………….3 2.4 时钟芯片通信电路……………………………………………………....……3

3. 软件模块设计...............................................................................................4

3.1 主程序设计……………………………………………………………….……….4 3.2 时钟芯片…………………………………………………………..………………5

3.2.1 DS1302内部结构……………………………………………………………5 3.2.2 DS1302的读时序……………………………………………………………6 3.2.3 DS1302的写时序……………………………………………………………6 3.3 键盘调时………………………………………………………………..…………7

4. 设计总结……………………………………………………………………………8 5. 参考文献……………………………………………………………………………8 6. 附录……………………………………………………………………………………9

3

××大学××学院××系××课程设计报告

前言

数字钟是采用数字电路实现对时、分、秒及数字显示的计时装置,广泛用于个人家庭、车站、办公室等公共场所,成为人们日常生活中的必需品。钟表的数字化给人们生产生活带来了极大的方便,而且大大的扩展了钟表原先的报时功能。如定时报警器、按时自动打铃、时间程序自动控制、自动开关路灯、定时电气的自动启用等。所有这些都是以钟表数字化为基础的。因此,研究数字钟及扩大其应用,有现实意义。

钟表的数字化大力推动了计时的精确性和可靠性。在单片机工程的装置中,实时时钟必不可少。目前常用的实时时钟,很多采用单片机中断服务实现。这种方式一方面需要采用计数器,占用硬件资源,另一方面需要设置中断、查询,浪费单片机资源。虽然能满足对实时时钟的要求,但是占用地址、数据总线多,给其他设计带来不便。

本次设计选择串行时钟芯片DS1302与单片机同步通信构成数字时钟电路。三线接口能为单片机节省大量资源。DS1302的后备电源以及对后备电源进行涓流充电的能力保证电路断电后仍能保存时间和数据信息。这些优点解决了目前常用的实时时钟无法解决的问题。

4

××大学××学院××系××课程设计报告

1.总体设计方案

1.1 电子钟功能介绍

1.1.1 基本功能介绍

第一点:电子时钟用8位数码管显示。

第二点:时间显示格式为XX-XX-XX,分别为时、分、秒。

1.1.2 扩展功能介绍

第一点:设计的电子时钟可以通过安检切换现实日历,其格式为XX-XX-XX,分别

为年、月、日。

第二点:设计的电子时钟可以进行时间的校准功能。

1.2 总体设计方案

1.2.1 计时方案

利用STC89C52单片机内部定时/计数器和时钟芯片DS1302进行终端定时,配合软件延时实现时、分、秒的计时。方案节省硬件成本,并且能使读者在定时/计数器的使用、中断及程序设计方面得到锻炼和提高,对单片机指令系统能有更升入的了解。

1.2.2 按键方案

STC89C52外接8个LED数码管显示,外接4个按键构成按键控制部分。

时钟电路 STC89C52 数码管显示 按键控制部

图1 设计方案图

1

××大学××学院××系××课程设计报告

1.2.3 显示方案

八段数码管显示有两种,一种是共阳数码管,其内部是八个阳极相连接的发光二极

管组成;另一种是共阴极数码管,其内部是八个阴极连接的发光二级管组成。二者原理不同但功能相同。本设计选用8个共阳八段数码管LED。

2.单元模块设计

2.1硬件总电路设计

图2 硬件电路图

2.2显示模块电路设计

设计主要使用数码管功能实现,显示部分硬件用8只数码管为显示管。这些数码管的阳极相连接在一起,所以称为共阳极数码管。通过在8只数码管的阳极加+5V电压或0V电压数码管形成不同的数字。数码管部分如图所示。

动态显示:数码管动态显示接口是单片机应用中最广泛的一种显示方式。动态是将所有数码管的8个显示笔画a,b,c,d,e,f,g,dp的同名端连接在一起,另外为每个数码管的公共级COM增加位选通控制电路。位选通由各自独立的I/O线控制,当单片机输出字型码时,所有数码管都接收到相同的字型码,当选择哪个数码管显示字形时,就取决于单片机对选通COM端电路的控制。所以我们只要将需要显示的数码管的选通控制打开,

2

××大学××学院××系××课程设计报告

该为显示字形。没有选通的数码管不会亮。通过分时控制各个数码管的COM端,就使个个数码管轮流受控显示,这就是动态驱动。

图3 显示电路图

2.3 按键调时电路

图4 键盘电路图

2.4 时钟芯片通信电路

时钟芯片DS1302与单片机STC89C52的借口是由三条线来完成的,单片机

STC89C52的P2.3与时钟芯片的数据传输端相连,P1.7用作DS1302的输入时钟SCLK控制线。P1.3控制DS1302的复位控制端。DS1302接标准32.768KHZ石英晶振。

DS1302与单片机的接口电路如图。

图5 时钟芯片电路图

3

××大学××学院××系××课程设计报告

3. 软件模块设计

主程序设计

开始 初始化定时器t0以及DS1302 从DS1302获取时间并转换为十进制 K1=0 NO YES 时钟调整 数码管显示时间 K4=0 NO YES 闹钟设置 闹钟次数加1 保存闹钟设置数据 获得的时间与闹钟设置的时间进行对比 时间相同 YES 蜂鸣器打开继电器打开 定时器打开 NO 图6 主程序设计图

4

3.1

××大学××学院××系××课程设计报告

3.2 时钟芯片

开始 向DS1302的某 个地址写入数据 向DS1302的某 个地址读取数据 将读取的数据赋 值给bakedata

返回bakedata

图7 时钟芯片流程图

3.2.1 DS1302内部结构:

图8 DS1302内部构造图

5

××大学××学院××系××课程设计报告

3.2.2 DS1302的读时序:

图9 读时序图

3.2.3 DS1302的写时序:

图10 写时序图

3.3 键盘调时

6

××大学××学院××系××课程设计报告

按键调整时间 开始 按键设置闹钟 开始 K2=0 NO K2=0 NO YES 从DS1302中获取的小时值加1 YES 当前小时值加1 并保存 K3=0 NO K3=0 NO YES 从DS1302中获取的分钟值加1 YES 当前分钟值加1 并保存 NO 返回 K1=0 YES 时钟启动

图11 键盘调时流程图

4.设计总结

在这学期的课程设计中,在收获知识的同时,还收获了阅历,收获了成熟,在此过程中,我们通过查找大量资料,请教老师,以及不懈的努力,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。更重要的是,在实验课上,我们学会了很多学习的方法。而这是日后最实用的,受益匪浅。要面对社会的挑战,只有不断的

7

××大学××学院××系××课程设计报告

学习、实践。在这次设计过程中,体现出自己单独设计模具的能力以及综合运用知识的能力,体会了学以致用、突出自己劳动成果的喜悦心情,从中发现自己平时学习的不足和薄弱环节,从而加以弥补。在此感谢××,××, ××老师,他们一丝不苟的作风一直是我工作、学习中的榜样;老师循循善诱的教导和不拘一格的思路给予我无尽的启迪。同时,对给过我帮助的所有同学和各位指导老师表示忠心的感谢!

5.参考文献

[1]楼然苗,李光飞.51系列单片机设计实例[M].北京:北京航空航天大学出版社,2003.88-100 [2]李群芳,黄建.单片机微型计算机与接口技术[M].北京:电子工业出版社,2001.70-82 [3]李朝青.单片机原理接口技术(第三版)[M].北京:北京航空航天大学出版社,2005,1-320 [4]赵嘉蔚.单片机原理与接口技术[M].北京:清华大学出版社,2010.2-26 [5]赵小安.MCS-51单片机原理及应用[M].天津:天津大学出版社,2001.3-35

[6]欧伟明,周春临,翟遂春.电子信息系统设计[M].西安:西安电子科技大学出版,2005,54

8

××大学××学院××系××课程设计报告

附录:程序代码

#include #include

#define uchar unsigned char #define uint unsigned int

sbit K1 = P3^0; sbit K2 = P3^1; sbit K3 = P3^2; sbit K4 = P3^3;

sbit P2_5 = P2^5; sbit P2_6 = P2^6; sbit P2_7 = P2^7;

sbit RST = P1^7; sbit IO = P2^3; sbit SCLK = P1^3; bit K1_FLAG = 0; 未按下时,该位为0 bit flag;

uchar code table[]={ 0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; uchar disp_buf[8]; uchar time_buf[7];

期、年

//定义K1键 //定义K2键 //定义K3键 //定义K4键

//定义按键标志位,当按下K1键时,该位置1,K1键

//定义显示缓冲区

//DS1302时间缓冲区,存放秒、分、时、日、月、星

9

××大学××学院××系××课程设计报告

uchar time_hour[10]; uchar time_min[10]; uchar temp[2]; uchar t0;

//用来存放设置时的小时、分钟的中间值

//定时器标志变量

/***********************函数声明********************************/ void dula(void); void wela(void);

//段选 //位选

//打开蜂鸣器

//关闭蜂鸣器

void ON_Buzzer(void); void OFF_Buzzer(void); void ON_Relay(void); void OFF_Relay(void); void Delay(uchar i);

//打开继电器 //关闭继电器

//延时

void Write_byte(uchar inbyte); //写一个字节 uchar Read_byte(void);

//读一个字节

//向DS1302写入地址和数据

void Write_ds1302(uchar address, uchar indata);

uchar Read_ds1302(uchar addr); //根据给定的地址读数据 void init_ds1302(void); void init_timer0(void); void Key_Process(void); void Key_Clock(void); void get_time(void);

//DS1302初始化 //定时器初始化

//按键检测并作出响应

//按键设置闹钟时间

//获取时间(进制转换)

//时间显示 //日历显示

void Time_Display(void);

void Date_Display(void);

/***************************主函数************************************/ void main() {

uint i = 0; uint j; P0 = 0;

P2 = 0; init_ds1302();

10

//设置闹钟数

××大学××学院××系××课程设计报告

init_timer0(); while(1) { get_time(); //读取当前时间 if(K1 == 0)

//若K1键按下

{ Delay(5); //延时10ms去抖

if(K1 == 0) { while(!K1); //等待K1键释放

K1_FLAG = 1;

//K1键标志位置1,以便进行时钟调整 }

}

if(K1_FLAG == 1) Key_Process(); //若K1_FLAG为1,则进行走时调整 Time_Display(); if(K4 == 0) { Delay(5); if(K4 == 0) { while( !K4); Key_Clock();

time_hour[i] = temp[0]; time_min[i] = temp[1]; i++; if(K4 == 0) { Delay(5); if(K4 == 0)

{

11

××大学××学院××系××课程设计报告

行 Write_ds1302(0x80,0x00); //调整完毕后,启动时钟运

Write_ds1302(0x8e,0x80); //写保护控制字,禁止写

}

}

}

}

for(j=0; j<=i; j++) { if((time_hour[j] == time_buf[2]) && (time_min[j] == time_buf[1])) { flag = 1; TR0 = 1; t0 = 0; ON_Relay(); ON_Buzzer(); } }

if(flag == 1) { OFF_Relay(); OFF_Buzzer(); TR0 = 0; flag = 0;

}

}

}

/*******************************延时程序*****************************/ void Delay(uchar i) {

12

××大学××学院××系××课程设计报告

uchar j; for ( ; i>0; i--) { for (j=110; j>0; j--);

}

}

/***********************数码管**********************************/ void dula(void) //段选

{ P2_5 = 1; P2_6 = 1; P2_7 = 1;

}

/*---------------------------------------------------------------------------*/ void wela(void) //位选

{ P2_5 = 0; P2_6 = 1; P2_7 = 1;

}

/**************************蜂鸣器*******************************/ void ON_Buzzer(void) //打开蜂鸣器

{ P2_5 = 1; P2_6 = 0; P2_7 = 1; P0 = 0x40; P2_5 = 0; P2_6 = 0; P2_7 = 0;

}

13

××大学××学院××系××课程设计报告

/*---------------------------------------------------------------------------*/ void OFF_Buzzer(void) //关闭蜂鸣器

{ P2_5 = 1; P2_6 = 0; P2_7 = 1; P0 = 0; P2_5 = 0; P2_6 = 0; P2_7 = 0;

}

/****************************继电器*********************************/ void ON_Relay (void) //继电器打开

{ P2_5 = 1; P2_6 = 0; P2_7 = 1; P0 = 0x10; P2_5 = 0; P2_6 = 0; P2_7 = 0;

}

/*---------------------------------------------------------------------------*/ void OFF_Relay (void) //继电器关闭

{ P2_5 = 1; P2_6 = 0; P2_7 = 1; P0 = 0; P2_5 = 0;

P2_6 = 0;

14

××大学××学院××系××课程设计报告

P2_7 = 0;

}

/******************初始化DS1302函数***************************/ void init_ds1302(void) {

RST = 0; SCLK = 0;

Write_ds1302(0x80,0x00); //写秒寄存器 Write_ds1302(0x90,0xab); //写充电器

Write_ds1302(0x8e,0x80); //写保护控制字,禁止写 }

/******************定时器初始化***********************************/ void init_timer0(void) { TMOD |= 0x01;

TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) / 256; ET0 = 1; EA = 1; TR0 = 0;

}

/****************************写一个字节******************************/ void Write_byte(uchar inbyte) {

uchar i; for(i=0; i<8; i++) { SCLK = 0; //写时低电平改变数据 if(inbyte & 0x01)

{

IO = 1;

15

××大学××学院××系××课程设计报告

}

else {

IO = 0;

}

SCLK = 1; //高电平把数据写入DS1302 _nop_();

inbyte = inbyte >> 1;

} }

/*********************读一个字节*********************************/ uchar Read_byte(void) {

uchar i,temp=0; IO=1; for(i=0; i<7; i++) { SCLK = 0; if(IO == 1)

{ temp = temp | 0x80;

} else

{ temp = temp & 0x7f;

}

SCLK = 1; //产生下跳沿 temp = temp >> 1;

}

return (temp); }

16

××大学××学院××系××课程设计报告

/**********************向DS1302写入数据************************/ void Write_ds1302(uchar address,uchar indata) {

SCLK = 0; RST = 1;

Write_byte(address); //写入地址 Write_byte(indata);

//写入数据

SCLK = 0; RST = 0; }

/**********************从DS1302读取数据*****************************/ uchar Read_ds1302(uchar addr) {

uchar backdata; SCLK = 0; RST = 1;

Write_byte(addr);

//先写地址

backdata=Read_byte(); //然后读数据

SCLK = 0; RST = 0; return (backdata); }

/************************按键扫描及操作******************************/ void Key_Process(void)

//通过按键调整时间

{

uchar min16,hour16;

//定义16进制的分钟和小时变量 Write_ds1302(0x8e,0x00);

//DS1302写保护控制字,允许写 Write_ds1302(0x80,0x80); //时钟停止运行 if(K2 == 0) //K2键用来对小时进行加1调整

{

Delay(5);

//延时去抖

17

××大学××学院××系××课程设计报告

if(K2 == 0) {

while( !K2);

//等待K2键释放

time_buf[2] ++; //小时加1 if(time_buf[2] == 24) { }

time_buf[2] = 0;//当变成24时初始化为0

hour16 = time_buf[2]/10*16 + time_buf[2];

}

Write_ds1302(0x84,hour16); //将调整后的小时数据写入DS1302

//将所得的小时数据转变成16进制数据

}

if(K3 == 0) {

Delay(5);

// K3键用来对分钟进行加1调整

//延时去抖

if(K3 == 0)

{

while( !K3);

//等待K3键释放

time_buf[1] ++; //分钟加1 { }

time_buf[1] = 0;//当分钟加到60时初始化为0 if(time_buf[1] == 60)

min16 = time_buf[1]/10*16 + time_buf[1];

}

18

//将所得的分钟数据转变成16进制数据

Write_ds1302(0x82,min16); //将调整后的分钟数据写入DS1302

}

××大学××学院××系××课程设计报告

if(K1 == 0)

//K4键是确认键

{ Delay(5);

//延时去抖

if(K1 == 0) { while( !K1);

//等待K1键释放

Write_ds1302(0x80,0x00); //调整完毕后,启动时钟运行 Write_ds1302(0x8e,0x80);

//写保护控制字,禁止写

K1_FLAG = 0;

//将K1键按下标志位清0

}

} }

/*---------------------------------------------------------------------------*/ void Key_Clock(void)

//按键设置闹钟时间

{

Write_ds1302(0x8e,0x00); //DS1302写保护控制字,允许写

// Write_ds1302(0x80,0x80); //时钟停止运行 if(K2 == 0)

//K2键用来对小时进行加1调整

{ Delay(5);

//延时去抖

if(K2 == 0) { while( !K2);

//等待K2键释放

temp[0] = time_buf[2]; temp[0]++;

//小时加1

if(temp[0] == 24) { temp[0] = 0;//当变成24时初始化为0

} //

time_hour[] = time_buf[2];

//将所得的小时数据转变成16进制数据

19

××大学××学院××系××课程设计报告

Write_ds1302(0x84,hour16); //将调整后的小时数据写入

//

DS1302

}

if(K3 == 0) {

Delay(5);

//延时去抖

// K3键用来对分钟进行加1调整

}

if(K3 == 0) {

Write_ds1302(0x82,min16); //将调整后的分钟数据写入

while( !K3);

//等待K3键释放

temp[1] = time_buf[1]; temp[1]++;

//分钟加1

if(temp[1] == 60) { }

time_min[] = time_buf[1];

//将所得的分钟数据转变成16进制数据 temp[1] = 0;//当分钟加到60时初始化为0

//

//

DS1302 }

/*************获取秒、分钟、小时、日、月、年的值******************************/ void get_time(void) {

uchar sec,min,hour,date,mouth,year;

//定义秒、分和小时变量

}

}

Write_ds1302(0x8e,0x00); //控制命令,WP=0,允许写操作

20

Write_ds1302(0x90,0xab); //涓流充电控制

××大学××学院××系××课程设计报告

sec = Read_ds1302(0x81); //读取秒 min = Read_ds1302(0x83); //读取分 hour = Read_ds1302(0x85); //读取时

time_buf[0] = sec/16*10 + sec; //将读取到秒的16进制数转化为10进制

time_buf[1] = min/16*10 + min; //将读取到分的16进制数转化为10进制

time_buf[2] = hour/16*10 + hour; //将读取到时的16进制数转化为10进制

time_buf[3] = date/16*10 + date;

//将读取到日的16进制数转化为

date = Read_ds1302(0x86);

//读取日 //读取月 //读取年

mouth= Read_ds1302(0x88); year = Read_ds1302(0x8c);

10进制

time_buf[4] = mouth/16*10 + mouth;

//将读取到月的16进制数转化为

10进制

time_buf[5] = year/16*10 + year;

//将读取到年的16进制数转化为

10进制 }

/********************数码管显示时间程序**********************************/ void Time_Display(void) {

wela(); P0 = 0xfd;

21

//秒-分-时显示

wela(); P0 = 0xfe; dula();

P0 = table[time_buf[0]/10]; //显示秒十位 Delay(5);

××大学××学院××系××课程设计报告

dula();

P0 = table[time_buf[0]]; //显示秒各位

Delay(5);

wela(); P0 = 0xfb; dula(); P0 = 0x40; Delay(5);

wela(); P0 = 0xf7; dula();

P0 = table[time_buf[1]/10]; //显示分十位 Delay(5);

wela(); P0 = 0xef; dula();

P0 = table[time_buf[1]]; //显示分各位

Delay(5);

wela(); P0 = 0xdf; dula(); P0 = 0x40; Delay(5);

wela(); P0 = 0xbf; dula();

22

××大学××学院××系××课程设计报告

P0 = table[time_buf[2]/10]; //显示时十位 Delay(5);

wela(); P0 = 0x7f; dula();

P0 = table[time_buf[2]]; //显示时各位

Delay(5);

}

/*---------------------------------------------------------------------------*/ //void Date_Display(void) //日-月-年显示

//{ // wela(); // P0 = 0xfe; // dula();

// P0 = table[time_buf[3]/10]; //显示日十位 // Delay(5); //

// wela(); // P0 = 0xfd; // dula();

// P0 = table[time_buf[3]]; //显示日各位

// Delay(5); //

// wela(); // P0 = 0xfb; // dula(); // P0 = 0x40; // Delay(5); //

// wela();

23

××大学××学院××系××课程设计报告

// P0 = 0xf7; // dula();

// P0 = table[time_buf[4]/10]; //显示月十位 // Delay(5); //

// wela(); // P0 = 0xef; // dula();

// P0 = table[time_buf[4]]; //显示月各位

// Delay(5); //

// wela(); // P0 = 0xdf; // dula(); // P0 = 0x40; // Delay(5); //

// wela(); // P0 = 0xbf; // dula();

// P0 = table[time_buf[5]/10]; //显示年十位 // Delay(5); //

// wela(); // P0 = 0x7f; // dula();

// P0 = table[time_buf[5]]; //显示年各位

// Delay(5); //}

/**********************定时器响应程序***********************************/ void t0_ser()

interrupt 1

24

××大学××学院××系××课程设计报告

{ TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) / 256; t0 ++; if(t0 == 1200) { OFF_Relay(); OFF_Buzzer(); TR0 = 0; }

}

25

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

Top