人人范文网 范文大全

基于51单片机电子时钟设计

发布时间:2020-03-02 08:17:39 来源:范文大全 收藏本文 下载本文 手机版

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

摘要

本电子时钟以STC89C52单片机作为主控芯片,采用DS12C887时钟芯片,使用1602液晶作为显示输出。该时钟走时精确,具有闹钟设置,以及可同时显示时间、日期等多种功能。本文将详细介绍该电子时钟涉及到的一些基本原理,从硬件和软件两方面进行分析。

【关键词】

STC89C52单片机

DS12C887时钟芯片

1602液晶

蜂鸣器

一、绪论…………………………………………………………4

1.1 电子时钟功能…………………………………………

4 1.

2设计方案………………………………………………4

二、硬件设计……………………………………………………4

2.

151

2.2 单片机部分设计………………………………4

USB供电电路设计………………………………5

2.3 串行通信电路设计………………………………6

2.

4DS12C887时钟芯片电路的设计…………………6

2.

51602LCD液晶屏显示电路设计………………7

2.6

蜂鸣器电路设计………………………………8

2.7

按键调整电路设计…………………………8

三、软件设计…………………………………………9

3.1 系统程序流程图设计…………………………9

3.

2程序设计……………………………………11

四、心得体会………………………………………………22 参考文献……………………………………………………23

一、绪

1.1电子时钟功能

(1)在1602液晶上显示年、月、日、星期、时、分、秒,并且按秒实时更新显示。 (2)具有闹铃设定即到时报警功能,报警响起时按任意键可取消报警。

(3)能够使用实验板上的按键随时调节各个参数,四个有效键分别为功能选择键、数值增大键、数值减小键和闹钟查看键。

(4)每次有键按下时,蜂鸣器都以短“滴”声报警。

(5)利用DS12C887自身掉电可继续走时的特性,该时钟可实现断电时间不停、再次上电时时间仍准确显示在液晶上的功能。

1.2设计方案

DS12C887时钟芯片+1602LCD液晶屏

DS12C887时钟芯片功能丰富、价格适中,能够自动产生世纪、年、月、日、时、分、秒等时间信息,其内部含有世纪寄存器,从而利用硬件电路解决“千年”问题。DS12C887中自带锂电池,外部掉电时,其内部时间信息还能保持10年之久。1602LCD液晶屏可以输出2行,每行显示16个字符。1602LCD液晶屏显示清晰且不会闪烁,由于液晶屏是数字式的,因此和单片机系统的接口简单,操作方便。

以STC89C52为主控芯片,DS12C887为时钟芯片,1602LCD液晶屏作为显示器。程序控制DS12C887时钟芯片实现小时、分、秒和年、月、日的计时,并在1602LCD液晶屏上显示出来。当时间走到程序所设定的时间时,蜂鸣器响起,起到闹钟功能。

二、硬

2.1 51单片机部分设计

单片机部分如图2—1所示:

以STC89C52单片机为核心,选用12MHZ的晶振,由于晶振的频率越高,单片机的运行速度就越快,考虑到单片机的运行速度快会导致对存储器的要求就会变高,因此12MHZ为最佳选择。外接电容的值虽然没有严格的要求,但是外接电容的大小会影响振荡器的频率高低、振荡器的稳定性和起振的快速性 ,因此选用30pF的电容作为起振电容。复位电路为按键高电平复位,当按键按下,RES端为高电平,当高电平持续4us的时间单片机即复位。

2.2 USB供电电路设计

USB供电电路如下图2—2所示:

该电子时钟采用USB端口的方式为单片机供电,LPOW1为电源显示灯,当按键S5按下,电源显示灯LPOW1亮,表示给单片机供+5V电。

2.3 串行通信电路设计

串行通信电路如下图2—3所示:

图中通过MAX232进行RS—232电平与单片机TTL电平之间的转换,从而为单片机和上位机之间通信提供通道。通信电路的目的就是让通信双方的电平匹配,单片机用的是TTL电平,上位机的串口用的是RS—232电平。TTL电平逻辑1的电压范围是+3.3V到+5V,逻辑0的电压范围是0到+3.3V;RS—232电平的逻辑1的电压范围是—15V到—5V,逻辑0的电压范围是+5V到+15V。MAX232可以把输入的+5V电源电压变换成为RS—232输出电平所需的+10V电压。所以采用此芯片接口的串行通信系统只需单一的+5V电源就可以了。对于没有+12V电源的场合,其适应性更强,

2.4 DS12C887时钟芯片电路的设计

时钟芯片电路如下图2—4所示:

DS12C887时钟芯片共需要13条信号线,分别是并行数据地址复用线AD0~AD7,CS,AS,R/W,DS和IRQ。

MOT—总线操作时序选择端。它有两种工作模式,当MOT接

VCC时,选用Motorola模式;当MOT接GND或悬空时,选用Intel模式。 NC—空引脚。

AD0~AD7—复用地址数据总线。在总线周期的前半部分,出现在AD0~AD7上的是地址信息,可用以选通DS12C887内的RAM,总线周期的后半部分出现在AD0~AD7上的是数据信息。 GND,VCC—系统电源接入端。当

VCC输入为+5V时,用户可以访问DS12C887内RAM

的输入小于+4.25V时,禁止用户对内部RAM中的数据,并可对其进行读/写操作;当

VCC进行读/写操作,此时用户不能正确芯片内的时间信息;当

VCC的输入小于+3V时,DS12C887会自动的将电源切换到内部自带的锂电池上,以保证内部的电路能正常工作。

CS—芯片片选端。

AS—地址选通输入端。在进行读/写操作时,AS的上升沿将AD0~AD7上出现的地址信息锁存到DS12C887上,而下一个下降沿清除AD0~AD7上的地址信息,不论CS是否有效,DS12C887都将执行该操作。

R/W—读/写输入端。该引接脚有两种工作模式,当MOT接

VCC时,R/W工作在Motorola模式。此时该引脚的作用是区分读操作还是写操作,R/W高电平时为读操作,R/W为低电平时为写操作;当MOT接GND时,该引脚工作在Intel模式,此时该引脚为写允许输入,此信号的上升沿锁存数据。

DS—数据选择或读输入脚。该引脚有两种工作模式,当MOT接

VCC时,选用Motorola模式,此时,每个总线周期后一部分的DS为高电平,称为数据选通。在读操作中,DS的上升沿使DS12C887将内部数据送往总线AD0~AD7上,以供外部读取。在写操作中,DS的下降沿将使总线AD0~AD7上的数据锁存在DS12C887中。当MOT接GND时,选用Intel模式,此时该引脚是读允许输入引脚。

RESET—芯片复位引脚。

IRQ—中断请求输出。用作处理器的中断申请输入。只要引起中断的状态位置位,并且相应中断使能位也置位,IRQ将一直保持低电平,处理器程序通常读取C存储器来清除IRQ引脚输出,RESET引脚也会清除未处理的中断。没有中断发生时,IRQ为高阻状态,可将多个中断器件接到一条IRQ总线上,只要它们均为漏极开路输出即可。IRQ引脚为漏极开路输出,需要使用一个外接上拉电阻与SQW—方波输出引脚。当供电电压

VCC相连。

VCC大于4.25V时,SQW引脚可输出方波。

2.5 1602LCD液晶屏显示电路设计

1602LCD液晶屏显示电路如下图2—5所示:

1602液晶为5V电压驱动,带背光,可显示2行,每行16个字符,不能显示汉字,内置含128个字符的ASCII字符集字库,只有并行接口,无串行接口。 接口说明如下: (1)液晶1,2端为电源;15,16为背光电源;为防止直接加5V电压烧坏背光灯,在15脚串接一个1K电阻用于限流。

(2)液晶3端为液晶对比度调节端,通过一个10K电位器接地来调节液晶显示对比度。首次使用时,在液晶上电状态下,调节至液晶上面一行显示出黑色小格为止。

(3)液晶4端为向液晶控制器写数据/写命令选择端,接单片机的P3.5口。

(4)液晶5端为读/写选择端,因为我们不从液晶读取任何数据,只向其写入命令和显示数据,因此此端始终选择为写状态,即低电平接地。

(5)液晶6端为使能信号,是操作时必须的信号,接单片机的P3.4口。

2.6 蜂鸣器电路设计

蜂鸣器电路如下图2—6所示:

蜂鸣器电路接在单片机的P2.3引脚上,当该引脚一个低电平,三极管导通,蜂鸣器发出声音作为闹铃。

2.7 按键调整电路设计

按键调整电路如下图2—7所示:

四个独立键盘均采用查询方式,将按键的一端接地,另一端各接一根输入线直接与STC89C52的I/O口相连。当按键闭合时,相当于该I/O口通过按键与地相连,变成低电平,单片机通过检测I/O口的电平状态,即可识别出按下的键。通过四个键实现参数的调节,S1为功能选择键,S2为数值增大键,S3为数值减小键,S4为闹钟查看键。

三、软

3.1 系统程序流程图设计

流程图1:实验主程序流程图

流程图2:定时中断程序流程图

流程图3:调时功能流程图

3.2 程序设计

#include #include void delay(uint z)

//延时函数 {

uint x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--); } void di( )

//蜂鸣器报警声音 {

beep=0;

delay(100);

beep=1; } void

write_com(uchar com)

//写液晶命令函数

{

rs=0;

lcden=0;

P0=com;

delay(3);

lcden=1;

delay(3);

lcden=0; } void write_data(uchar

data)

//写液晶数据函数 {

rs=1;

lcden=0;

P0=data;

delay(3);

lcden=1;

delay(3);

lcden=0; } void

init( )

//初始化函数 {

uchar

num;

EA=1;

//打开总中断

EX1=1;

//开外部中断1

IT1=1;

//设置负跳变沿触发中断

flag1=0;

//变量初始化

t0_num=0;

s1num=0;

week=1;

dula=0;

//关闭数码管显示

wela=0;

lcden=0;

rd=0; /*以下几行在首次设置DS12C887时使用,以后不必再写入

write_ds(0x0A,0x20);

//打开振荡器

write_ds(0x0B,0x26);

//设置24小时模式,数据二进制格式,开启闹铃中断

set_time( );

//设置上电默认时间

---------------*/

write_com(0x38);

//1602液晶初始化

write_com(0x0c);

write_com(0x06);

write_com(0x01);

write_com(0x80);

for(num=0;num

//写入液晶固定部分显示

{

write_data(table[num]);

delay(1); }

write_com(0x80+0x40);

for(num=0;num

{

write_data(table1[num]);

delay(1);

} } void write_sfm(uchar add,char data)

{ //1602液晶刷新时分秒函数,4为时,7为分,10为秒

char

shi,ge;

shi=data/10;

ge=data%10;

write_com(0x80+0x40+add);

write_data(0x30+shi);

write_data(0x30+ge); } void

write_nyr(uchar add,char

data)

{

//1602液晶刷新年月日函数,3为年,6为月,9为日

char

shi,ge;

shi=data/10;

ge=data%10;

write_com(0x80+add);

write_data(0x30+shi);

write_data(0x30+ge); void

write_week(char we)

//写液晶星期显示函数 {

write_com(0x80+12);

switch(we)

{

case 1:

write_data(\'M\');delay(5);

write_data(\'O\');delay(5);

write_data(\'N\');

break;

case 2:

write_data(\'T\');delay(5);

write_data(\'U\');delay(5);

write_data(\'E\');

break;

case 3:

write_data(\'W\');delay(5);

write_data(\'E\');delay(5);

write_data(\'D\');

break;

case 4:

write_data(\'T\');delay(5);

write_data(\'H\');delay(5);

write_data(\'U\');

break;

case 5:

write_data(\'F\');delay(5);

write_data(\'R\');delay(5);

write_data(\'I\');

break;

case 6:

write_data(\'S\');delay(5);

write_data(\'A\');delay(5);

write_data(\'T\');

break;

case 7:

write_data(\'S\');delay(5);

write_data(\'U\');delay(5);

write_data(\'N\');

break;

} } void keyscan( ) { if(flag_ri==1) {

//这里用来取消闹钟报警,按任意键取消报警

if((s1==0)||(s2==0)||(s3==0)||(s4==0))

{

delay(5);

if((s1==0)||(s2==0)||(s3==0)||(s4==0))

{

while(!(s1&&s2&&s3&s&s4));di( );

flag_ri=0;

//清除报警标志

}

}

}

if(s1==0)

//检测s1

{

delay(5);

if(s1==0)

{

s1num++;

//记录按下次数

if(flag1==1)

if(s1num==4)

s1num=1;

flag=1;

while(!s1);di( );

switch(s1num)

{

//光标闪烁点定位

case 1: write_com(0x80+0x40+10);

write_com(0x0f);

break;

case 2: write_com(0x80+0x40+7);

break;

case 3: write_com(0x80+0x40+4);

break;

case 4: write_com(0x80+12);

break;

case 5: write_com(0x80+9);

break;

case 6: write_com(0x80+6);

break;

case 7: write_com(0x80+3);

break;

case 8: s1num=0;

write_com(0x0c);

flag=0;

write_ds(0,miao);

write_de(2,fen);

write_ds(4,shi);

write_ds(6,week);

write_ds(7,day);

write_ds(8,month);

write_ds(9,year);

break;

}

}

}

if(s1num!=0)

//只有当s1按下后,才检测s2和s3

{

if(s2==0)

{

delay(1);

if(s2==0)

while(!s2);di( );

switch(s1num)

{

//根据功能键次数调节相应数值

case 1: miao++;

if(miao==60)

miao=0;

write_sfm(10,miao);

write_com(0x80+0x40+10);

break;

case 2: fen++;

if(fen==60)

fen=0;

write_sfm(7,fen);

write_com(0x80+0x40+7);

break;

case 3: shi++;

case 4:

case 5:

case 6:

case 7:

}

}

}

if(s3==0)

{

delay(1);

if(shi==24)

shi=0;

write_sfm(4,shi);

write_com(0x80+0x40+4);

break; week++;

if(week==8)

week=1;

write_week(week);

write_com(0x80+12);

break; day++;

if(day==32)

day=1;

write_nyr(9,day);

write_com(0x80+9);

break; month++;

if(month==13)

month=1;

write_nyr(6,month);

write_com(0x80+6);

break; year++;

if(year==100)

year=0;

write_nyr(3,year);

write_com(0x80+3);

break;

if(s3==0)

{

while(!s3);di( );

switch(s1num)

{

//根据功能键次数调节相应数值

case 1: miao--;

if(miao==-1)

miao=59;

write_sfm(10,miao);

write_com(0x80+0x40+10);

break;

case 2: fen--;

if(fen==-1)

fen=59;

write_sfm(7,fen);

write_com(0x80+0x40+7);

break;

case 3: shi--;

if(shi==-1)

shi=23;

write_sfm(4,shi);

write_com(0x80+0x40+4);

break;

case 4: week--;

if(week==0)

week=7;

write_week(week);

write_com(0x80+12);

break;

case 5: day--;

if(day==0)

day=31;

write_nyr(9,day);

write_com(0x80+9);

break;

case 6: month--;

if(month==0)

month=12;

write_nyr(6,month);

write_com(0x80+6);

break;

case 7: year--;

if(year==-1)

year=99;

write_nyr(3,year);

write_com(0x80+3);

break;

}

}

}

}

if(s4==0)

//检测s4

{

delay(5);

if(s4==0)

{

flag1=~flag1;

while(!s4);di( );

if(flag1==0)

{

//退出闹钟设置时保存数值

flag=0;

write_com(0x80+0x40);

write_data(\' \');

write_data(\' \');

write_com(0x0c);

write_ds(1,miao);

write_ds(3,fen);

write_ds(5,shi);

}

else

{

//进入闹钟设置

read_alarm( );

//读取原始数据

miao=amiao;

//重新赋值用以按键调节

fen=afen;

shi=ashi;

write_com(0x80+0x40);

write_data(\'R\');

//显示标志

write_data(\'i\');

write_com(0x80+0x40+3);

write_sfm(4,ashi);

//送液晶显示闹钟时间

write_sfm(7,afen);

write_sfm(10,amiao);

}

}

} } void write_ds(uchar add,uchar

data) {

//写12C887函数

dscs=0;

dsas=1;

dsds=1;

dsrw=1;

P0=add;

//先写地址

dsas=0;

dsrw=0;

P0=data;

//再写数据

dsrw=1;

dsas=1;

dscs=1; } uchar

read_ds(uchar add) {

//读12C887函数

uchar

ds_data;

dsas=1;

dsds=1;

dsrw=1;

dscs=0;

P0=add;

//先写地址

dsas=0;

dsds=0;

P0=0xff ;

ds_data=P0;

//再读数据

dsds=1;

dsas=1;

dscs=1;

return ds_data; } /*---首次操作12C887时给予寄存器初始化----- void set_time( ) {

//首次上电初始化时间函数

write_ds(0,0);

write_ds(1,0);

write_ds(2,0);

write_ds(3,0);

write_ds(4,0);

write_ds(5,0);

write_ds(6,0);

write_ds(7,0);

write_ds(8,0);

write_ds(9,0); } ----------------------*/

void

read-alarm( ) {

//读取12C887闹钟值

amiao=read_ds(1);

afen=read_ds(3);

ashi=read_ds(5); } void main( )

//主函数 {

init( );

//调用初始化函数

while(1)

{

keyscan( );

//按键扫描

if(flag_ri==1)

//当闹钟中断时进入这里

{

di( );

delay(100);

di( );

delay(500);

}

if(flag==0&&flag1==0)

//正常工作时进入这里

{

keyscan( );

//按键扫描

year=read_ds(9);

//读取12C887数据

month=read_ds(8);

day=read_ds(7);

week=read_ds(6);

shi=read_ds(4);

fen=read_ds(2);

miao=read_ds(0);

write_sfm(10,miao);

//送液晶显示

write_sfm(7,fen);

write_sfm(4,shi);

write_week(week);

write_nyr(3,year);

write_nyr(6,month);

write_nyr(9,day);

}

} } void

exter( ) interrupt 2

//外部中断1服务程序 {

uchar

c;

//进入中断表示闹钟时间到

flag_ri=1;

//设置标志位,用于大程序中报警提示

c=read_ds(0x0c);

//读取12C887的C寄存器表示响应了中断 }

_______________________________________________________________________________ 以下为define.h源代码:

_______________________________________________________________________________ #define uchar unsigned char #define uint unsigned int sbit dula=P2^6; sbit wela=P2^7; sbit rs=P3^5; sbit lcden=P3^4; sbit s1=P3^0;

//功能键 sbit s2=P3^1;

//增大键 sbit s3=P3^2;

//减小键 sbit s4=P3^6;

//闹钟查看键 sbit rd=P3^7; sbit beep=P2^3;

//蜂鸣器 sbit dscs=P1^4; sbit dsas=P1^5; sbit dsrw=P1^6; sbit dsds=P1^7; sbit dsirq=P3^3; bit flag1,flag_ri;

//定义两个位变量

uchar count,s1num,flag,t0_num;

//其他变量定义 char miao,shi,fen,year,month,day,week,amiao,afen,ashi; uchar code

table[]=\"201-

\";

//液晶固定显示内容 uchar code

table1[]=\"

:

:

\";

void write_ds(uchar,uchar);

//函数申明 void set_alarm(uchar,uchar,uchar); void read_alarm( ); uchar read_ds(uchar); void set_time( );

四、心

在本次电子时钟设计中对单片机的内部结构有了一定的了解,熟悉了各个引脚的功能,同时熟知了1602LCD液晶、DS12C887时钟芯片的使用,以及各种电路的功能。

通过此次课程设计,无论是从软件方面还是硬件方面,都进一步学习和巩固了程序的总体设计和单片机的应用。在软件方面,进一步熟悉了各条指令的功能及用法,定时、中断的用法,更深一步学习了用C语言编写实现电子时钟的功能。在硬件方面,进一步熟悉并使用了keil软件,在keil中编程,调试,运行;对电路的一些基本结构和设计有了更深一步的了解。在整个设计过程中,虽然出现了很多问题,有时确实叫人很心烦,但在发现问题后努力去解决,并获得成功,这时会感到无比的快乐和具有成就感。只有自己动手去做,去应用,才能将学到的知识变成自己的。

程序不要光看不写,一定要自己写一次。最开始的时候,可能自己啥都不懂,这时可以抄人家的程序过来。但在抄的时候一定要看看每一句是干什么用的,来达到什么目的,运行后有什么后果,看明白了之后,就要自己写一次。此时会发现,原来看明白别人的程序很容易,但到自己写的时候却一句也写不出来,这就是差距。

单片机提高重在实践,想要学好单片机,软件编程必不可少。但是熟悉硬件对于学好单片机也是非常重要的。如何学习好硬件,动手实践是必不可少的。我们可以通过自己动手做一个自己的电子制作,通过完成它,以提高对一些芯片的了解和熟练运用。这样我们就可以多了解一些芯片的结构。

我学习的目标是希望在若干年以后能够独立设计一个复杂的系统,包括硬件电路和软件部分。总之,通过这次电子技术设计我学到了许多,似乎离自己的目标又近了一步。

[1]郭天祥 . 51单片机C语言教程 .电子工业出版社 . 2009 [2]谭浩强 . C程序设计 . 清华大学出版社 .

1991 [3]孙育才 王荣兴

孙华芳 . ATMEL新型AT89S52系列单片机及其应用 . 清华大学出版社 .

2006 [4]谢维成 .

单片机原理及应用与51程序设计 .

清华大学出版社 .

2006

[5]鲍宏亚 . MCS—51系列单片机应用系统设计及实用技术 .

中国宇航出版社 .

2005 [6]赵文博

刘文涛 .

单片机语言C51程序设计 . 人民邮电出版社 .

2006 [7]求是科技 .

8051系列单片机C程序设计 .

人民邮电出版社 .

2006

单片机课程设计 (51单片机实现电子时钟)

单片机课程设计报告,单片机电子时钟

单片机电子时钟课程设计报告

单片机课程设计电子时钟说明书

电子时钟 单片机实习报告(推荐)

AVR单片机的时钟设计

数字电子时钟设计

51单片机毕业论文

51单片机论文

基于51单片机的电子广告牌电路设计

基于51单片机电子时钟设计
《基于51单片机电子时钟设计.doc》
将本文的Word文档下载到电脑,方便编辑。
推荐度:
点击下载文档
点击下载本文文档