资源描述
目 录
1、引言 ·····················································3
2、总体设计 ···············································4
3、详细设计 ············································5
3.1硬件设计 ···········································5
3.2软件设计 ··········································10
4、实验结果分析············································26
5、心得体会·················································27
6、参考文献·················································27
摘 要
单片机自20世纪70年代问世以来,以其极高的性能价格比,受到人们的重视和关注,应用很广、发展很快。单片机体积小、重量轻、抗干扰能力强、环境要求不高、价格低廉、可靠性高、灵活性好、开发较为容易。由于具有上述优点,在我国,单片机已广泛地应用在工业自动化控制、自动检测、智能仪器仪表、家用电器、电力电子、机电一体化设备等各个方面,而51单片机是各单片机中最为典型和最有代表性的一种。这次毕业设计通过对它的学习、应用,以AT89S51芯片为核心,辅以必要的电路,设计了一个简易的电子时钟,它由4.5V直流电源供电,通过数码管能够准确显示时间,调整时间,从而到达学习、设计、开发软、硬件的能力。
关键词: 单片机 AT89C51
1.引言
20世纪末,电子技术获得了飞速的发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高,产品更新换代的节奏也越来越快。 时间对人们来说总是那么宝贵,工作的忙碌性和繁杂性容易使人忘记当前的时间。忘记了要做的事情,当事情不是很重要的时候,这种遗忘无伤大雅。但是,一旦重要事情,一时的耽误可能酿成大祸。
目前,单片机正朝着高性能和多品种方向发展趋势将是进一步向着CMOS化、低功耗、小体积、大容量、高性能、低价格和外围电路内装化等几个方面发展。下面是单片机的主要发展趋势。单片机应用的重要意义还在于,它从根本上改变了传统的控制系统设计思想和设计方法。从前必须由模拟电路或数字电路实现的大部分功能,现在已能用单片机通过软件方法来实现了。这种软件代替硬件的控制技术也称为微控制技术,是传统控制技术的一次革命。
单片机模块中最常见的是数字钟,数字钟是一种用数字电路技术实现时、分、秒计时的装置,与机械式时钟相比具有更高的准确性和直观性,且无机械装置,具有更更长的使用寿命,因此得到了广泛的使用.
数字钟是采用数字电路实现对.时,分,秒.数字显示的计时装置,广泛用于个人家庭,车站, 码头办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表, 钟表的数字化给人们生产生活带来了极大的方便。
2.总体设计
1、准确计时,以数字形式显示时、分、秒的时间。
2、小时以24小时计时形式,分秒计时为60进位。
3、校正时间功能,即能随意设定走时时间。
4、设计5V直流电源,系统时钟电路、复位电路。
本次设计时钟电路,使用了ATC89C51单片机芯片控制电路,单片机控制电单且省去了很多复杂的线路,使得电路简明易懂,使用键盘键上的按键来调整时钟的时、分、秒, 采用实时时钟芯片
现在市场上有很多实时时钟集成电路,如DS1287、DS12887、DS1302等。
实时时芯片具备年、月、日、时、分、秒计时功能和多点定时功能,计时数据的更新每秒自动进行一次,不需要程序干预。因此,在工业实时测控系统中多采用这一类专用芯片来实现实时时钟功能。
总设计原理框图如下图所示:
微型控制器
时钟电路
时间可调
时钟芯片
数据显示
3.详细设计
3.1硬件设计
3.1.1、STC89C51单片机介绍
STC89C51单片机内部主要包括累加器ACC(有时也简称为A)、程序状态字PSW、地址指示器DPTR、只读存储器ROM、随机存取存储器RAM、寄存器、并行I/O接口P0~P3、定时器/计数器、串行I/O接口以及定时控制逻辑电路等。这些部件通过内部总线联接起来,构成一个完整的微型计算机。其管脚图如图
STC89C51单片机管脚结构图
VCC:电源。
GND:接地。
P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程 序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作 输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。
P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻 拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存 储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器 的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
P3口也可作为AT89C51的一些特殊功能口,如下表所示:
口管脚 备选功能
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 /INT0(外部中断0)
P3.3 /INT1(外部中断1)
P3.4 T0(记时器0外部输入)
P3.5 T1(记时器1外部输入)
P3.6 /WR(外部数据存储器写选通)
P3.7 /RD(外部数据存储器读选通)
P3口同时为闪烁编程和编程校验接收一些控制信号。
RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE 端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器 时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。
PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
EA/VPP:当/EA保持低电平时,则在此期间外部程序存储(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时, /EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
3.1.2、上电按钮复位电路
本设计采用上电按钮复位电路:首先经过上电复位,当按下按键时,RST直接与VCC相连,为高电平形成复位,同时电解电容被电路放电;按键松开时,VCC对电容充电,充电电流在电阻上,RST依然为高电平,仍然是复位,充电完成后,电容相当于开路,RST为低电平,单片机芯片正常工作。其中电阻R2决定了电容充电的时间,R2越大则充电时间长,复位信号从VCC回落到0V的时间也长。
3.1.3、晶振电路
本设计晶振电路采用12M的晶振。晶振的作用是给单片机正常工作提供稳定的时钟信号。单片机的晶振并不是只能用12M,只要不超过20M就行,在准许的范围内,晶振越大,单片机运行越快,还有用12M的就是好算时间,因为一个机器周期为1/12时钟周期,所以这样用12M的话,一个时钟周期为12us,那么定时器计一次数就是1us了,电容范围在20-40pF之间,这里连接的是30pF的电容。
机器周期=10*晶振周期=12*系统时钟周期
3.1.4.下载端口
设计用到的STC89C52单片机芯片的ISP下载线是通过单片机的TXD,RXD引脚把程序烧进去的。管脚TXD和RXD用于异步串行通信。其实STC89C52单片机的ISP下载线就是一个max232芯片连接STC和计算机的串行通信口。计算机把程序从九针串口送到max232芯片,电平转换后送进单片机的串行口,也就是TXD和RXD。然后单片机的串行模块把数据送到程序区。
3.1.5、显示电路
就时钟而言,通常可采用液晶显示或数码管显示。由于一般的段式液晶屏要专门的驱动电路,而且液晶显示具有亮度高、价格便宜等优点。
3.1.6时钟显示校正电路
本设计利用按键开关来校正时钟显示的数字。当按钮按下时,将在相应的端口输入一个低电平,通过相应的程序来改变时钟显示。其中S1按键开关用来选择要修改的数字;S2按键用来增加所选数字的数值;S3按键用来减少所选数字的数值。
3.2软件设计
3.2.1主程序。
主程序主要用于系统初始化:设置计时缓冲区的位置及初值,设置8155的工作方式、定时器的工作方式和计数初值等参数。主程序流程如下图所示。
开始
定义堆栈区
8155、 T0、数据缓冲区、标志位初始化
调用键盘扫描程序
否
是C/R键?
是
地址指针指向计时缓冲区
调用时间设置程序
主程序流程图
3.2.2计时。
即定时器0中断子程序,完成刷新计时缓冲区的功能。
系统使用6MHz的晶振,假设定时器0工作在方式1,则定时器的最大定时时间为65.536ms,这个值远远小于1s。因此本系统采用定时器与软件循环相结合的定时方法。设定时器0工作在方式1,每隔50ms溢出中断一次,则循环中断20次延时时间是1s,上述过程重复60次为1分,分计时60次为1小时,小时计时24次则时间重新回到00:00:00。
因定时器0工作在方式1,则50ms定时对应的定时器初值为:65536-50ms/2us=40536=9E58H,即TH0=9EH,TH0=58H。
但应当指出:CPU从响应T0中断到完成定时器初值重装这段时间,定时器T0并不停止工作,而是继续计数。因此,为了确保T0能准确定时50ms,重装的定时器初值必须加以修正,修正的定时器初值必须考虑到从原定时器初值中扣除计数器多计的脉冲个数。由于定时器计数脉冲的周期恰好和机器周期吻合,因此修正量等于CPU从响应中断到重装完TL0为止所用的机器周期数。CPU响应中断通常要3~8个机器周期。经过测试,定时器0重装的计数初值设为9E5FH~9E67H,可以满足精度要求。另外,MCS-51单片机只有二进制加法指令,而时间是按十进制递增,因此用加法指令后必须进行二-十进制转换。
计时模块流程图如下图所示。
保护现场
重装定时器初值
循环次数减1
否
满20次?
是
秒单元加1
否
60s到?
是
秒单元清0,分单元加1
否
60分到?
是
分单元清0,时单元加1
否
24小时到?
是
时单元清0
恢复现场
返回
3.2.3时间设置模块。
该模块由键盘输入相应的数据来设置当前时间。程序通过调用一个键盘设置子程序通过键盘扫描将键入的6位时间值送入显示缓冲区。
设置时间后,时钟要从这个时间开始计时,而时分秒单元各占一个字节,键盘占6个字节。因此程序中要调用一个合字子程序将显示缓冲区中的6位BCD码合并为3位压缩BCD码,并送入计时缓冲区,作为当前计时起始时间。
该程序同时要检测输入时间值的合法性,若键盘输入的小时值大于23,分、秒值大于59,则不合法,将取消本次设置,清零重新开始计时。
时间设置和键盘设置子程序的流程图如下图所示。
保护现场
调用键盘设置子程序KETIN
调用合字子程序COMB
恢复现场
返回
时间设置流程图
保护现场
显示缓冲区首地址送R0键盘输入次数送R7
调用键盘扫描程序KEYSCAN
键号送@R0
显示缓冲区地址加1
循环次数减1
否
循环结束?
是
恢复现场
返回
键盘设置子程序流程图
3.2.4显示。
连接电源后,调整时间,lcd屏上会显示出年月日时分秒。
显示程序流程图如下图所示。
保护现场
否
允许显示?
调用拆字程序
是
动态扫描显示
返回
显示程序流程图
扫描键盘
否
调用显示程序 有键按下?
是
调用显示程序
否
有键按下?
是
求取键号
返回
键盘扫描程序流程图
3.2.5程序:
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define PIN P0
sbit LCDE=P2^7;
sbit RW=P2^5;
sbit RS=P2^6;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit sck=P3^6;
sbit io=P3^4;
sbit RST=P3^5;
uint w[7]={0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //写地址
uint r[7]={0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; //读地址
char num1[10]="0123456789";
unsigned char time1[7]={0x50,0x59,0x23,0x04,0x11,0x02,0x14};
uint second,hour,min,num,a,time[7];
uint nian,yue,ri,shi,fen,miao,zhou;
void delay(uint z) //延时程序
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void writecom(uchar com) //LCD写命令
{
LCDE=0;
RS=0;
RW=0;
PIN=com;
delay(10);
LCDE=1;
delay(10);
LCDE=0;
}
void writedata(uchar dat) //LCD写数据
{
LCDE=0;
RS=1;
RW=0;
PIN=dat;
delay(10);
LCDE=1;
delay(10);
LCDE=0;
RS=0;
}
void LCDINIT() //初始化LCD
{
delay(1000);
LCDE=0;
RW=0;
writecom(0x38);设置显示模式
writecom(0x0c);不显示光标,光标不闪烁
writecom(0x06);写一个指针加1
writecom(0x01);清屏
writecom(0x80);设置数据指针起点
}
void ds1302writebyte(uint dat) //ds1302写单个数据
{
uint i;
sck=0;
_nop_();
_nop_();
for(i=0;i<8;i++)
{
io=dat&0x01;
dat>>=1;
_nop_();
_nop_();
sck=1;
_nop_();
_nop_();
sck=0;
_nop_();
_nop_();
}
}
uint ds1302readbyte() //1302读单个数据
{
uint i,value;
sck=0;
_nop_();
_nop_();
for(i=0;i<8;i++)
{
value>>=1;
if(io)
{
value=value|0x80;
}
sck=1;
_nop_();
_nop_();
sck=0;
_nop_();
_nop_();
}
return value;
}
void ds1302wr(uint add,uint dat) //多个字节写入
{
RST=0;
_nop_();
sck=0;
_nop_();
RST=1;
_nop_();
ds1302writebyte(add);
ds1302writebyte(dat);
RST=0;
_nop_();
}
uint ds1302rd(uint add) //读取多个数据
{
uint ks;
RST=0;
_nop_();
sck=0;
_nop_();
RST=1;
_nop_();
ds1302writebyte(add);
ks=ds1302readbyte();
RST=0;
_nop_();
io=0; //此条语句必不可少。如果少了这条语句的话,液晶显示会不完全。
_nop_();
io=1;
_nop_();
return ks;
}
void Ds1302Init()
{
unsigned char n;
ds1302wr(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for(n=3;n<7;n++)//写入7个字节的时钟信号:分秒时日月周年
{
ds1302wr(w[n],time1[n]);
}
ds1302wr(0x8E,0x80); //打开写保护功能
}
void rdtime() //1302读初始时间
{
miao=ds1302rd(r[0]);
fen=ds1302rd(r[1]);
shi=ds1302rd(r[2]);
zhou=ds1302rd(r[5]);
ri=ds1302rd(r[3]);
yue=ds1302rd(r[4]);
nian=ds1302rd(r[6]);
}
void display()
{
//显示函数
int i,j,a[8];
writecom(0x80);
a[0]=(num1[(nian)/16]); // 年
a[1]=(num1[(nian)%16]);
a[2]=0X3A;
a[3]=num1[yue/16]; //月
a[4]=num1[yue%16];
a[5]=0X3A;
a[6]=num1[ri/16]; //日
a[7]=num1[ri%16];
for( i=0;i<8;i++)
{
writedata(a[i]);
delay(10);
}
writecom(0x80+0x40+7);
a[0]=(num1[(shi)/16]); //小时
a[1]=(num1[(shi)%16]);
a[2]=0X3A;
a[3]=num1[fen/16]; //分钟
a[4]=num1[fen%16];
a[5]=0X3A;
a[6]=num1[miao/16]; //秒钟
a[7]=num1[miao%16];
for(j=0;j<8;j++)
{
writedata(a[j]);
}
}
void showtime(uint address,uint time)
{
delay(500);
writedata(num1[time%16]);
writecom(0x80+0x40+address);
writedata(num1[time/16]);
writecom(0x80+0x40+1+address);
writecom(0x0f);
}
void keyscan() //键盘扫描函数
{
if (0==k1) //K1时间停止
{
delay(10);
if(0==k1)
{
num++;
while(num>0&&num<=8)
{
if (0==k1)
{
if(0==k1)
{ num++;
while(!k1)
{
switch(num)
{
case 2:
{
uint i;
num++;
a=1;
writecom(0x80+0x40+0x0e);
writecom(0x0f);
for(i=0;i<7;i++)
{
time1[i]=ds1302rd(r[i]);;
}
}
break;
case 4:
{
num++;
writecom(0x80+0x40+0x0b);
writecom(0x0f);
}
break;
case 6:
{
num++;
writecom(0x80+0x40+0x08);
writecom(0x0f);
}
break;
case 8:
{
num=0;
a=0;
Ds1302Init();
delay(10);
writecom(0x0c);
}
break;
}
}
}
}
if(0==k2)
{
delay(5);
if(0==k2)
{
while(!k2)
switch(num) //K2,时,分,秒加数
{
case 3:
{
if(9==time1[0]%16)
{
time1[0]+=6;
}
time1[0]++;
if(time1[0]==0x60)
time1[0]=0;
showtime(0xd,time1[0]);
}
break;
case 5:
{
if(9==time1[1]%16)
{
time1[1]+=6;
}
++time1[1];
while(0x60==time1[1])
time1[1]=0;
showtime(0xa,time1[1]);
}
break;
case 7:
{
if(9==time1[2]%16)
{
time1[2]+=6;
}
++time1[2];
while(0x24==time1[2])
time1[2]=0;
Ds1302Init();
showtime(7,time1[2]);
}
break;
}
}
}
if(0==k3)
{
delay(5);
if(0==k3)
{
while(!k3)
switch(num) //K3,时,分,秒减数
{
case 3:
{
if(0==time1[0]%16)
{
time1[0]-=6;
if((0-6)==time1[0])
time1[0]=0x5a;
}
--time1[0];
showtime(0x0d,time1[0]);
}
break;
case 5:
{
if(0==time1[1]%16)
{
time1[1]-=6;
if((0-6)==time1[1])
time1[1]=0x5a;
}
--time1[1];
showtime(0x0a,time1[1]);
}
break;
case 7:
{
if(0==time1[2]%16)
{
time1[2]-=6;
if((0-6)==time1[2])
time1[2]=0x5a;
}
--time1[2];
showtime(0x07,time1[2]);
}
break;
}
}
}
}
}
}
}
void main()
{
Ds1302Init();
LCDINIT();
while(1)
{
keyscan();
rdtime();
display();
}
}
4.实验结果与分析
5.心得体会
我在这一次电子钟的设计过程中,很是受益匪浅。通过对自己在大学三年时间里所学的知识的回顾,并充分发挥对所学知识的理解和对毕业设计的思考及书面表达能力,最终完成了。这为自己今后进一步深化学习,积累了一定宝贵的经验。撰写论文的过程也是专业知识的学习过程,它使我运用已有的专业基础知识,对其进行设计,分析和解决一个理论问题或实际问题,把知识转化为能力的实际训练。培养了我运用所学知识解决实际问题的能力。
通过这次课程设计我发现,只有理论水平提高了;才能够将课本知识与实践相整合,理论知识服务于教学实践,以增强自己的动手能力。这个实验十分有意义 我获得很深刻的经验。通过这次课程设计,我们知道了理论和实际的距离,也知道了理论和实际想结合的重要性,也从中得知了很多书本上无法得知的知识。
我们的学习不但要立足于书本,以解决理论和实际教学中的实际问题为目的,还要以实践相结合,理论问题即实践课题,解决问题即课程研究,学生自己就是一个专家,通过自己的手来解决问题比用脑子解决问题更加深刻。学习就应该采取理论与实践结合的方式,理论的问题,也就是实践性的课题。这种做法既有助于完成理论知识的巩固,又有助于带动实践,解决实际问题,加强我们的动手能力和解决问题的能力。
参考文献
[1] 谢自美.电子线路设计·实验·测试[M].武汉:华中理工大学出版社,1992.
[2] 何立民.单片机应用系统设计[M].北京:北京航空航天大学出版社,1993.
[3] 楼然笛.单片机开发[M].北京:人民邮电出版社,1994.
[4] 付家才.单片机控制工程实践技术[M].北京:化学工业出版社 2004.3.
[5] 李光才.单片机课程设计实例指导[M].北京:北京航空航天大学出版社 2004.
[6] 朱定华.单片机原理及接口技术实验[M].北京:北方交通大学出版社2002.11.
[7] 刘湘涛.江世明.单片机原理与应用[M]. 北京:电子工业出版社,2006.
29
展开阅读全文