文档库

最新最全的文档下载
当前位置:文档库 > (完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

单片机原理课程设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

题目: 基于AT89C52的电子时钟设计

姓名:

学院:

专业:

班级:

学号:

指导教师:

年月日

南京农业大学教务处制

aortiu

目录

摘要 (2)

关键词 (2)

引言 (2)

1设计要求与方案论证 (2)

1.1设计要求 (2)

1.2系统方案选择方案和论证 (2)

1.2.1单片机芯片的选择方案和论证 (2)

1.2.2 显示模块选择方案和论证 (3)

1.2.3 时钟芯片的选择方案和论证 (3)

2.系统的硬件设计与实现 (3)

2.1电路设计框图 (3)

2.2系统硬件概述 (3)

2.3主要单元电路的设计 (4)

2.3.1 单片机主控制模块的设计 (4)

2.3.2时钟电路模块的设计 (4)

2.3.3 键盘模块设计 (5)

2.3.4蜂鸣器模块的设计 (5)

2.3.5显示模块的设计 (5)

3.系统的软件设计 (6)

3.1程序流程框图 (6)

3.2程序的设计 (7)

4.系统调试 (7)

4.1软件调试 (7)

4.2硬件调试 (8)

4.3 实验箱调试结果 (8)

5.总结心得体会 (9)

附录一:系统程序 (9)

基于AT89C52的电子时钟设计

指导教师:吕成绪胡飞

摘要:单片机在电子产品中的应用越来越广泛,特别是51系列的单片机,由于其使用方便、价格低廉等优势,在市场上占有很大的份额。AT89C52就是51系列中的一个比较成熟的型号。本设计是一个多功能的实时时钟,带秒表、整点报时、闹铃、调整时间等功能。可按键直接设置闹铃时间。由AT89C51单片机、DS1302、LCD1602等模块组成。现代社会,时间就是金钱,时钟是每个人的必备品。本设计实现了所需功能,给大家带来方便,整体性好、人性化强、可靠性高,实现了时钟的多功能应用。

关键词:电子时钟;DS1302;LCD1602;

引言:

随着科技的快速发展,时间的流逝,从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS1302。它可以对年、月、日、周、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。对于数字电子时钟采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。该设计以AT89C51单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。

综上所述,此电子时钟具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。

1.设计要求与方案

1.1 设计要求:

(1)启动时显示制作的年、月、日、制作者的学号等信息。

(2)24小时计时功能(精确到秒)

(3)整点报时功能。

(4)秒表功能

(5)省电功能模式(未设计)

1.2 系统基本方案选择

1.2.1单片机芯片的选择方案和论证

方案一:

采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容,但是运用于电路设计中时由于不具备ISP在线编程技术, 当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,对芯片的多次拔插会对芯片造成一定的损坏。

方案二:

采用AT89S52,片内ROM全都采用Flash ROM;能以3V的超底压工作;同时也与MCS-51

系列单片机完全该芯片内部存储器为8KB ROM 存储空间,同样具有89C51的功能,且具有在线编程可擦除技术,当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,不需要对芯片多次拔插,所以不会对芯片造成损坏。

相比之下,我们在实验箱实际仿真时选择采用AT89S52作为主控制系统,由于proteus 库中没有AT89S52,在原理图仿真时采用了AT89C51. 1.2.2 显示模块选择方案和论证

方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用在显示数字显得太浪费,且价格也相对较高,所以也不用此种作为显示.

方案二:采用LCD 液晶显示屏,液晶显示屏的显示功能强大,显示多样,清晰可见. 本设计采用LCD1602.

1.2.3时钟芯片的选择方案和论证 方案一:

直接采用单片机定时计数器提供秒信号,使用程序实现年、月、日、时、分、秒计数。采用此种方案虽然减少芯片的使用,节约成本,但是,实现的时间误差较大。所以不采用此方案。

方案二:

采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能的时钟芯片,可自动对秒、分、时、日、周、月、年以及闰年补偿的年进行计数,而且精度高,位的RAM 做为数据暂存区,工作电压2.5V ~5.5V 范围内,2.5V 时耗电小于300nA.

综上各方案所述,对此次作品的方案选定: 采用AT89C52作为主控制系统, DS1302提供时钟计时,LCD1602屏幕显示.

2.系统的硬件设计与实现 2.1 电路设计框图

2.2 系统硬件概述

本电路是由AT89C51单片机为控制核心,具有在线编程功能,低功耗,能在3V 超低压工作;时钟电路由DS1302提供,它是一种高性能、低功耗、带RAM 的实时时钟电路,它可以对年、月、日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V ~5.5V 。采用三线接口与CPU 进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM 数据。DS1302内部有一个31*8的用于临时性存放数据的RAM 寄存器。可产

键盘模块 DS1302 时钟模块

LCD1602

显示模块

AT89C51 单片机 模 块

生年、月、日、周日、时、分、秒,具有使用寿命长,精度高和低功耗等特点,同时具有掉电自动保存功能;显示部份由LCD1602构成.

2.3主要单元电路的设计

2.3.1单片机主控制模块的设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

图-1 主控制系统

AT89C51单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3。

单片机的最小系统如上图所示,18引脚和19引脚接时钟电路,XTAL1接外部晶振和微调电容的一端,在片内它是振荡器倒相放大器的输入,XTAL2接外部晶振和微调电容的另一端,在片内它是振荡器倒相放大器的输出.第9引脚为复位输入端,接上电容,电阻及开关后够上电复位电路.如图-1 所示.

2.3.2时钟电路模块的设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

图-2 DS1302的引脚图

图-2示出DS1302的引脚排列,其中Vcc1为后备电源,Vcc2为主电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。X1和X2是振荡源,外接32.768KHz晶振。RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。如果在传送过程中RSTS置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。上电动行时,在Vcc大于等于2.5V之前,RST必须保持低电平。中有在SCLK 为低电平时,才能将RST置为高电平,I/O为串行数据输入端(双向)。SCLK始终是输入端。

2.3.3 键盘模块设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

图-3 键盘模块

如图-3,K1、K2、K3、K4均为多功能键。K1为秒表设置键,按K4键时为时钟确定键;K2在K4按下时为时钟下调键,在K3按下时为闹钟确定键,在K1按下时为秒表开始键;K3为闹钟设置键,在K4按下时为时钟上调键,在K1按下时为秒表暂停键;K4为时钟设置键,在K3按下时为闹钟移位键,在K1按下时为秒表退出键。

2.3.4蜂鸣器模块的设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

图-4 声音输出模块

闹铃时间到和整点时,P3_7给低电平,蜂鸣器响。

2.3.5显示模块的设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

图-5 LCD显示输出模块

如图—5,1脚VSS和3脚VEE为电源接地,第2管脚VDD接电源,第4管脚RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器;RW为读写信号线,高电平1时进行读操作,低电平0时进行写操作;E(或EN)端为使能(enable)端;第7~14脚D0~D7为8位双向数据端。控制和数据端都接了上拉电阻用来驱动。

3.系统的软件设计

3.1程序流程框图

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

图-A 主程序流程图

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

图-B 时间调整程序流程图

3.2程序的设计

见附录

4.系统调试

4.1软件调试结果

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

时钟主界面用户

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

设置闹铃界面秒表界面

(完整word版)单片机原理课程设计 基于AT89C52的电子时钟设计

时钟仿真图

4.2 硬件调试结果

起初蜂鸣器有点问题不响,后来发现是定义错端口引起的。其他功能正常。

4.3实验箱调试结果

实现功能的具体方法:

时钟主界面时按下K1键进入秒表功能,按K2秒表开始,再按K3秒表停,按键K4返回时间显示;按K4开始调试(移位“年→秒”),接着按K2、K3调节时间增减;按K2开启闹钟,K3调节时间,K4(移位“时分”);按“年→秒”的顺序移位,按键K2进行减运算,按键K3进行加运算,按键K1返回到主界面并显示设置值。

按下K3键,实现闹钟定时调整,按键K4进行“分-秒”移位,按键K3进行上调,按键K2返回到主界面。

主界面K2实现开启/关闭闹钟的功能。

按下K1键进入秒表,按键K2开始计时,K3暂停计时,K4返回到主界面。

5.总结心得体会:

这次实习我们组选择的是电子时钟设计。实习任务包括理论设计、调试与仿真、撰写设计报告等。其中理论设计又包括选择总体方案,硬件系统设计、软件系统设计;硬件设计包括单元电路,选择元器件及计算参数等;软件设计包括模块化层次结构图,程序流程图。程序设计是课程设计的关键环节,开始以为时钟会很简单,就算遇到问题应该也很好解决,但当自己真正去做的时候,发现了好多困难。于是查资料,问同学。经过和同学的探讨,通过调试进一步完善程序设计,最后虽然省电模式没实现但其他基本达到课题所要求的指标。完成了实习任务。这次实习我更加了解了单片机的应用,更加牢牢的掌握了书本知识与现实的结合,总之这是实习收获很大,以后还需多动手实践,多练习编程,才能熟练掌握单片机。

附录一:

程序:

#include

#include

#include

#include

#define uchar unsigned char

#define uint unsigned int

#define TIME (0X10000-50000)

#define FLAG 0xf4 //闹钟标志

sbit rst=P1^2; //DS

sbit clk=P1^0;

sbit dat=P1^1;

sbit rs=P2^0; //LCD

sbit rw=P2^1;

sbit e=P2^2;

sbit beep=P1^3;

sbit mbkey=P1^4;

uchar k;

uchar flag;

uchar i=20,j,time1[16];

uchar alarm[2],time2[15],time[3];time5[3];

uchar code Day[]={31,28,31,30,31,30,31,31,30,31,30,31}; //12个月的最大日期(非闰年)

uchar key2num,ms=0,mbmiao=0,mbfen=0,mbkeynum,num; //ms秒表进数,mbmiao.mbfen秒表的秒.分,key2num是key5的计数

uchar code table[]=" 32210324 GYY";

uchar code table1[]=" 32210326 GLQ";

uchar code table4[]=" 00:00:00 MB ";

void delay(uint z)

{ uint x,y;

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

for(y=110;y>0;y--);

}

delay1ms(uchar time) //延时1ms

{ uchar i,j;

for(i=0;i

{ for(j=0;j<250;j++);}

}

//LCD驱动部分

enable()

{ rs=0;

rw=0;

e=0;

delay1ms(3);

e=1;

}

write2(uchar i)

{ P0=i;

rs=1;

rw=0;

e=0;

delay1ms(2);

e=1;

}

write1(uchar data *address,m)

{ uchar i,j;

for(i=0;i

{ j=*address;

write2(j);

}

}

//LCD显示

lcdshow()

{ P0=0XC; //显示器开、光标关enable();

P0=0x80; //第一行0~15

enable();

write1(time1,16);

P0=0xc1; //第二行1~14

enable();

write1(time2,15);

}

//DS1302读写子程序

write(uchar address)

{ uchar i;

clk=0;

_nop_();

rst=1;

_nop_();

for(i=0;i<8;i++)

{ dat=address&1;

_nop_();

clk=1;

address>>=1;

clk=0;

}

}

uchar read()

{ uchar i,j=0;

for(i=0;i<8;i++)

{ j>>=1;

_nop_();

clk=0;

_nop_();

if(dat)

j|=0x80;

_nop_();

clk=1;

}

return(j);

}

//部分显示数据初始化

timestart()

{

time1[6]=time1[9]='-';

time1[2]='2',time1[3]='0';

time2[2]=time2[5]=':';

write(0xc1);

alarm[0]=read();

rst=0;

write(0xc3);

alarm[1]=read();

rst=0;

write(0xc5);

time1[0]=read();

rst=0;

}

//读取时间

readtime()

{ uchar i,m,n;

write(0x8d); //读取年份

m=read();

rst=0;

time1[4]=m/16+0x30;

time1[5]=m%16+0x30;

time1[15]=m+0x30;

for(i=7,n=0x89;i<11;i+=3,n-=2) //读取月份和日期

{ write(n);

m=read();

rst=0;

time1[i]=m/16+0x30;

time1[i+1]=m%16+0x30;

}

for(m=0,i=0,n=0x85;i<7;i+=3,n-=2,m++) //读取时,分,秒

{ write(n);

time[m]=read(); //将实时的时分秒给time[] rst=0;

time2[i]=time[m]/16+0x30;

time2[i+1]=time[m]%16+0x30;

}

}

baoshi() //整点报时

{ beep=1;

if(time[1]==0)

if(time[2]==0)

{beep=0;delay(10);beep=1;}

}

//闹钟部分

showalarm()

{ uchar i;

for(i=1;i<10;i++)

{beep=0;delay(1000);beep=1;}

}

//根据日期的变动自动调整星期

//设置时间

settime()

{

uchar i=0x85,year,month,day,n;

time2[6]=time2[7]=0x30,time1[14]=time1[15]=0x20;

lcdshow();

while(1)

{

P0=0x0e; //显示器开显示、开光标

enable();

P0=i; //定光标

enable();

P1=0xf0;

if(P1!=0Xf0) //有按钮按下

{

delay1ms(100); //延时0.1s去抖动

if(P1!=0Xf0)

{

j=7;

if(P1==0X70) //K1,设置时钟

{

i+=3;

if(i==0x8e)

i=0xc2;

else if(i>0xc5)

i=0x85;

}

else if(P1==0xb0) //K2,上调

{

year=(time1[4]&0xf)*10+(time1[5]&0xf);

month=(time1[7]&0xf)*10+(time1[8]&0xf);

day=(time1[10]&0xf)*10+(time1[11]&0xf);

if(i==0x85)

{

year++;

if(year>99)

year=0;

if((year%4)!=0)

if(month==2&&day==29)

day=28;

}

else if(i==0x88)

{

month++;

if(month>12)

month=1;

if(day>Day[month-1])

{

day=Day[month-1];

if(month==2&&(year%4)==0)

day=29;

}

}

else if(i==0x8b)

{

day++;

if(day>Day[month-1])

{

if(month==2&&(year%4)==0)

{

if(day>29)

day=1;

}

if(month!=2)

day=1;

}

}

else if(i==0xc2)

{

n=(time2[0]&0xf)*10+(time2[1]&0xf);

n++;

if(n>23)

n=0;

time2[0]=n/10+0x30;

time2[1]=n%10+0x30;

}

else

{

n=(time2[3]&0xf)*10+(time2[4]&0xf);

n++;

if(n>59)

n=0;

time2[3]=n/10+0x30;

time2[4]=n%10+0x30;

}

time1[4]=year/10+0x30;

time1[5]=year%10+0x30;

time1[7]=month/10+0x30;

time1[8]=month%10+0x30;

time1[10]=day/10+0x30;

time1[11]=day%10+0x30;

lcdshow();

}

else if(P1==0xd0) //K3,下调{ year=(time1[4]&0xf)*10+(time1[5]&0xf);

month=(time1[7]&0xf)*10+(time1[8]&0xf);

day=(time1[10]&0xf)*10+(time1[11]&0xf);

if(i==0x85)

{

year--;

if(year<1)

year=99;

if((year%4)!=0)

if(month==2&&day==29)

day=28;

}

else if(i==0x88)

{

month--;

if(month<1)

month=12;

if(day>Day[month-1])

{

day=Day[month-1];

if(month==2&&(year%4)==0)

day=29;

}

}

else if(i==0x8b)

{

day--;

if(day<1)

{

if(month==2&&(year%4)==0)

{

day=29;

}

if(month!=2)

day=Day[month-1];

}

}

else if(i==0xc2)

{

n=(time2[0]&0xf)*10+(time2[1]&0xf);

n--;

if(n<0)

n=23;

time2[0]=n/10+0x30;

time2[1]=n%10+0x30;

}

else

{

n=(time2[3]&0xf)*10+(time2[4]&0xf);

n--;

if(n<0)

n=59;

time2[3]=n/10+0x30;

time2[4]=n%10+0x30;

}

time1[4]=year/10+0x30;

time1[5]=year%10+0x30;

time1[7]=month/10+0x30;

time1[8]=month%10+0x30;

time1[10]=day/10+0x30;

time1[11]=day%10+0x30;

lcdshow();

}

else if(P1==0xe0) //K4,确定设置

{ delay1ms(1000);

write(0x8c);

write((time1[4]&0xf)*16+(time1[5]&0xf));

rst=0;

write(0x8a);

rst=0;

for(i=7,n=0x88;i<11;i+=3,n-=2)

{

write(n);

write((time1[i]&0xf)*16+(time1[i+1]&0xf));

rst=0;

}

for(i=0;i<7;i+=3,n-=2)

{

write(n);

write((time2[i]&0xf)*16+(time2[i+1]&0xf));

rst=0;

}

TR0=0;

return;

}

else

{

TR0=0;

return;

}

}

}

if(j==0)

{

TR0=0;

return;

}

}

}

//设置闹钟

setalarm()

{

uchar i,n;

for(i=1;i<16;i++)

{

time1[i]=0x20;

}

time2[0]=alarm[0]/16+0x30;

time2[1]=(alarm[0]&0x0f)+0x30;

time2[3]=alarm[1]/16+0x30;

time2[4]=(alarm[1]&0x0f)+0x30;

time2[6]=time2[7]=0x30;

lcdshow();

i=0xc2;

while(1)

{

P0=0xe; //显示器开、光标开

enable();

P0=i; //定光标

enable();

P1=0xf0;

if(P1!=0Xf0) //有按钮按下

{

delay1ms(100); //延时0.1s去抖动

if(P1!=0Xf0)

{

j=7;

if(P1==0X70)

{

i+=3;

if(i>0xc5)

i=0xc2;

}

else if(P1==0xb0) //按K2,设闹钟

{

if(i==0xc2)

{

n=(time2[0]&0xf)*10+(time2[1]&0xf);

n++;

if(n>23)

n=0;

time2[0]=n/10+0x30;

time2[1]=n%10+0x30;

}

else

{

n=(time2[3]&0xf)*10+(time2[4]&0xf);

n++;