诚 信 声 明
本人郑重声明:所呈交的毕业设计文本和成果,是本人在指导老师的指导下,独立进行研究所取得的成果。成果不存在知识产权争议,本毕业设计不含任何其他个人或集体已经发表过的作品和成果。本人完全意识到本声明的法律结果由本人承担。
毕业设计者签名:
年 月 日
摘要:本文介绍了基于at89s51单片机设计的电子数字秒表的调试和使用方法。本设计通过at89s51单片机以及单片机最小系统和三极管驱动以及外围的按键和数码管显示等部件,设计一个基于单片机的简易计时器。设计通过四位一体共阳极数码管显示,数码管前两位显示分钟,后两位显示秒。通过按键能对秒进行设置,并利用单片机内部存储器eeprom,可以存储十组数据,可进行正计时、倒计时的切换。当倒计时结束蜂鸣器报警,倒计时时间可设置,可以查看记录的数据,暂停,清零等功能。电子数字秒表计时器是能够精确的记录时间,广泛用于各种继电器、电磁开关、延时器、定时器等的时间测试;在体育竞技计时方面也得到广泛应用,拥有较强的实用性。
关键字:at89s51单片机;驱动芯片;四位一体数码管
前 言
时钟,自从它发明的那天起,就成为人类的朋友,但随着时间的推移,科学技术的不断发展,人们对时间计量的精度要求越来越高,应用越来越广。怎样让时钟更好的为人民服务,怎样让我们的老朋友焕发青春呢?这就要求人们不断设计出新型时钟。
现今,高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟,石英表,石英钟都采用了石英技术,因此走时精度高,稳定性好,使用方便,不需要经常调校,数字式电子钟用集成电路计时时,译码代替机械式传动,用led显示器代替显示器代替指针显示进而显示时间,减小了计时误差,这种表具有时,分,秒显示时间的功能,还可以进行时和分的校对,片选的灵活性好。
时间被认为是最宝贵的资源,为了对时间有更深刻的了解,同时也在电子方面有更深刻的认识,通过学习,本次设计主要介绍用单片机内部的定时/计数器来实现电子数字秒表的方法,本设计由单片机at89s51芯片和led数码管为核心,辅以必要的电路,构成了一个单片机电子数字秒表。相信它会越来越深入地浸透到人们的生活中,并且将在一定程度上影响人们对生活的理解和诠释。用单片机制作电子产品也会越来越多,也是众多领域实施编程开发不可缺少的一部分,这将必然成为一种趋势。为更多的了解单片机的原理和应用,故做此设计来进行巩固。
下面就是计时器设计的具体过程。
1绪论
1.1 课题研究的背景
随着科技的快速发展,时间的流逝,从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。从奥运会的计时技术的进步就可以看到计时科技的进步,一百多年过去了,首届现代奥运会上的计时所用的跑表到如今的一系列高科技计时装置,如高速数码摄像机、电子触摸垫、红外光束、无线应答器等等。随之当今计时技术的快速发展,即便千分之一秒的差距也决定着冠军的归属。在现在体育竞技比赛中,运动员的水平不断提高,差距也在不断缩小,这就要求对时间精度要求越来越高,有时冠军之间的差距只有几毫秒,因此就要高精度的秒表来记录成绩。在机械控制和家电计时运作与暂停都需要秒表来控制,这也是秒表的一个较为广泛的应用。秒表携带方便,成本低,应用广泛,具有广泛的市场前景。
1.2课题的研究目的与意义
电子数字秒表计时器是能够精确的记录时间,广泛用于各种继电器、电磁开关、延时器、定时器等的时间测试;在体育竞技计时方面也得到广泛应用,拥有较强的实用性。
制作电子数字秒表计时器能够对我们学习的知识进行一个系统的实践,进一步巩固和加深我们对基础理论知识、基本技能掌握,将知识进行系统化和技能操作的实践知识综合化。通过完成电子数字秒表计时器的设计、制作、调试,让我们对电子产品的整个制作过程有一个完整的认识,考验我们对电路的设计能力,程序的编译能力,以及产品的焊接组装能力,在实践中提高技能水平。
1.3课题解决的主要内容
本课题所研究的电子数字秒表是单片机控制技术的一个具体应用,主要研究内容包括以下几个方面:
(1)选用电子数字秒表芯片时,应重点考虑功能实在、使用方便、单片存储、低功耗、抗断电的器件。
(2)根据选用的电子数字秒表历芯片设计外围电路和单片机的接口电路。
(3)在硬件设计时,结构要尽量简单实用、易于实现,使系统电路尽量简单。
(4)根据硬件电路图,在开发板上完成器件的焊接。
(5)根据设计的硬件电路,编写控制at89s51芯片的单片机程序。
(6)通过编程、编译、调试,把程序下载到单片机上运行,并实现本设计的功能。
(7)在硬件电路和软件程序设计时,主要考虑提高人机界面的友好性,方便用户操作等因素。
设计任务:掌握单片机程序设计、调试和应用电路设计、分析及调试检测。
基本要求:设计一按键控制数码管显示的电子数字秒表,能实现存储十组数据,数码管前两位显示分钟,后两位显示秒,可完成正计时、倒计时可以切换。在倒计时结束时蜂鸣器报警,同时倒计时时间可自行设置。还可以查看记录的数据,具备暂停,清零等功能。
1.4系统硬件设计
1.4.1 电路设计框图
本设计通过at89s51单片机以及单片机最小系统和三极管驱动以及外围的按键和数码管显示等部件,设计一个基于单片机的简易计时器。设计通过四位一体共阳极数码管显示,并能通过按键对秒进行设置,对数据进行存储和查看。
图1 电路设计框图
1.4.2 功能实现
系统在正常工作时,led液晶上分和秒都显示为零,当按下k1键时,电子数字秒表开始计时,如果想要对时间进行调整,可以通过调整设置模块来实现。当按下k2键时,可以存储数据,每按一次存储一组数据,能存储最近十组数据。如想要倒计时可以按下k5键来调节倒计时的秒数,倒计时结束时蜂鸣器响五声后停止。如想要切换到正计时可以按下k4键,同时k5键还可以调闹钟,闹钟时间到时,蜂鸣器响五声数码管闪五下停止。如果想要退出重新计时就再按一下k6即可复位。
系统原理图如图2:
图2原理图
2软件设计
时间被认为是最宝贵的资源,为了对时间有更深刻的了解,同时也在电子方面有更深刻的认识,通过学习,选择做一个通过按键控制数码管的电子数字秒表设计,电子数字秒表的核心部件单片机at89s51,它在整个人类史上的地位已经不容置疑地确立了,相信它会越来越深入地浸透到人们的生活中,并且将在一定程度上影响人们对生活的理解和诠释。用单片机制作电子产品也会越来越多,也是众多领域实施编程开发不可缺少的一部分,这将必然成为一种趋势。为更多的了解单片机的原理和应用,故做此设计来进行巩固。
本电路以at89s51单片机最小系统为控制核心,数码管显示由三极管8550驱动,输入部分采用五个独立式按键k1、k2、k3、k4、k5。显示部分的型与单片机p0口相连,数码管的的位由单片机的p2口控制。对于不同型号的单片机只需要相应的改变一下地址即可。该软、硬件系统具有很好的通用性,很高的实际使用价值。
2.1 软件系统框图
系统设计图如图2所示。
图3 软件设计图
2.2 程序流程图
图4程序流程图
2.3 程序编写
void display();
char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //数字对应显示码表
char code tab1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//小数点
char code index[]={0xf7,0xfb,0xfd,0xfe}; //每位数字对应数码管显示位置
uc num[8]; //每位数字存放数组
uc val[10][4];//存储的记录 [10]为记录序列,[8]为每组记录中的数字
char val_index;//记录序列标志位
uc set_index,ok_flag,timing;
bit mode=1;//运行模式,1为正向计数,0为反向计数。
bit fin_flag=0;//完成标志位,当反向计数结束时,此位为高电平,触发蜂鸣器
bit set_shan;
sbit beep=p3^6; sbit key1=p1^0; sbit key2=p1^1; sbit key3=p1^2; sbit key4=p1^3; sbit key5=p1^4;
void delay(ui z)
{ ui i,j;
for(i=0;i<z;i++)
for(j=0;j<121;j++);
}
void init()//初始化设计
{ tmod=0x11; th0=0x4b; tl0=0xff; th1=0x4b; tr0=0;
tl1=0xff; et1=1; tr1=1; et0=1; ea=1;
val_index=0;
}
void clr()
{ uc i;
for(i=0;i<8;i++)
num[i]=0;
}
void setup()
{ ok_flag=0xff;
set_index=0;
while (ok_flag)
{ display();
if(key1==0) //按动key1设置值加1
{ delay(5);
if(key1==0)
{ if ((set_index==0)|(set_index==2)|(set_index==4)|(set_index==6))
{ num[set_index]++;
if(num[set_index]==10)
num[set_index]=0;
}
else if((set_index==1)|(set_index==3)|(set_index==5)|(set_index==7))
{ num[set_index]++;
if(num[set_index]==6)
num[set_index]=0;
}
while(!key1) display();
}
}
if(key2==0) //按动key2设置位置加1
{ delay(5);
if(key2==0)
{ set_index++;
if(set_index==8)
{ set_index=0;
if((num[4]!=0)||(num[5]!=0)||(num[6]!=0)||(num[7]!=0))
{
num[0]=0;num[1]=0;num[2]=0;num[3]=0;mode=1;
}
else if((num[4]==0)&&(num[5]==0)&&(num[6]==0)&&(num[7]==0))
{ if((num[0]==0)&&(num[1]==0)&&(num[2]==0)&&(num[3]==0))
mode=1;
else if((num[0]!=0)||(num[1]!=0)||(num[2]!=0)||(num[3]!=0))
mode=0;
}
}
while(!key2) display();
}
}
if(key5==0) //按动key5设置结束
{ delay(5);
if(key5==0)
{ ok_flag=0x00;
if((num[4]!=0)||(num[5]!=0)||(num[6]!=0)||(num[7]!=0))
{
num[0]=0;num[1]=0;num[2]=0;num[3]=0;mode=1;
}
else if((num[4]==0)&&(num[5]==0)&&(num[6]==0)&&(num[7]==0))
{ if((num[0]==0)&&(num[1]==0)&&(num[2]==0)&&(num[3]==0))
mode=1;
else if((num[0]!=0)||(num[1]!=0)||(num[2]!=0)||(num[3]!=0))
mode=0;
}
// mode=0;
while(!key5) display();
}
}
}
}
void display()
{ uc i;
if(ok_flag!=0xff)
{ if(timing==0)
{ for(i=0;i<4;i++)
{ p0=0xff;
p2=index[i];
if(i==2)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
}
}
else
{ if(set_shan==0)
{ for(i=0;i<4;i++)
{ p0=0xff;
p2=index[i];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
}
}
else if(set_shan==1)
{ for(i=0;i<4;i++)
{ p0=0xff;
p2=index[i];
if(i==2)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
}
}
}
}
else
{ if(set_shan==0)
{ if(set_index==0)
{ for(i=0;i<4;i++)
{ if(i==0)
{ p2=index[0];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
else
{ p2=index[i];
if(i==2)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
else if(set_index==1)
{ for (i=0;i<4;i++)
{ if(i==1)
{ p2=index[1];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
else
{ p2=index[i];
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
else if(set_index==2)
{ for (i=0;i<4;i++)
{ if(i==2)
{ p2=index[2];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
else
{ p2=index[i];
if(i==2)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
else if(set_index==3)
{ for (i=0;i<4;i++)
{ if(i==3)
{ p2=index[3];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
else
{ p2=index[i];
if(i==2)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
else if(set_index==4)
{ for (i=4;i<8;i++)
{ if(i==4)
{ p2=index[0];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
else
{ p2=index[i-4];
if(i==6)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
else if(set_index==5)
{ for (i=4;i<8;i++)
{ if(i==5)
{ p2=index[1];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
else
{ p2=index[i-4];
if(i==6)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
else if(set_index==6)
{ for (i=4;i<8;i++)
{ if(i==6)
{ p2=index[2];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
else
{ p2=index[i-4];
if(i==6)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
else if(set_index==7)
{ for (i=4;i<8;i++)
{ if(i==7)
{ p2=index[3];
p0=tab[10];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
else
{ p2=index[i-4];
if(i==6)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
}
else
{ if(set_index<4)
{ for (i=0;i<4;i++)
{ p2=index[i];
if(i==2)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
else
{ for (i=4;i<8;i++)
{ p2=index[i-4];
if(i==6)
p0=tab1[num[i]];
else
p0=tab[num[i]];
delay(2); //修改此参数可修改刷新频率
p0=0xff;
}
}
}
}
}
void alarm()
{ if((num[4]==0)&&(num[5]==0)&&(num[6]==0)&&(num[7]==0))
{timing=0;}
else
{
if((num[4]==num[0])&&(num[6]==num[2])&&(num[5]==num[1])&&(num[7]==num[3]))
{timing=1;tr0=0;}
}
}
void main()//主函数
{ uc h,g,k;
init();
clr();
while(1)
{ display(); //刷屏显示数码管
alarm();
if(key1==0) //开始/暂停按钮
{ delay(5);
if(key1==0)
{ tr0=~tr0;
while(!key1) display();
}
}
if(key2==0) //记录按钮
{ delay(5);
if(key2==0)
{ if(tr0==1)//当在运行中按下记录键则存储记录
{ for(g=1;g<10;g++)
{
for(k=0;k<4;k++)
{val[g-1][k]=val[g][k];}
}
for(h=0;h<4;h++)
{ val[9][h]=num[h];//将当前时间存储 }
}else//在停止状态下按下记录键查看记录,按动一次序列递减一次,即查看上一次记录
{ for(h=0;h<4;h++)
num[h]=val[val_index][h];//将当前时间存储
val_index--;
if(val_index<0)
val_index=9;
}
while(!key2) display();
}
}
if(key3==0) //复位按钮
{ delay(5);
if(key3==0)
{ clr(); while(!key3) display();}
}
if((key4==0)&&(tr0==0)) //模式选择按钮,仅在停止状态下有效
{ delay(5);
if(key4==0)
{ mode=~mode;
while(!key4) display();}
}
if((key5==0)&&(tr0==0)) //时间设置,仅在停止状态下有效
{ delay(5);
if(key5==0)
{ while(!key5)
display();
setup();}
}
}
}
void t0_time() interrupt 1
{ uc m;
th0=0x4b; //定时器定时时间为50ms
tl0=0xff;
m++;
if(m==20)
{ m=0;
if(mode==1) //正向计数
{ num[0]++;
if(num[0]==10)
{ num[0]=0;
num[1]++;
if(num[1]==6)
{ num[1]=0;
num[2]++;
if(num[2]==10)
{ num[2]=0;
num[3]++;
if(num[3]==10)
num[3]=0;}
}
}
}
else
{ num[0]--;
if(num[0]>9)
{ num[0]=9;
num[1]--;
if(num[1]>5)
{ num[1]=5;
num[2]--;
if(num[2]>9)
{ num[2]=9;
num[3]--;
if(num[3]>9)
{ num[3]=0;
tr0=0;
fin_flag=1;
clr();}
}
}
}
}
}
}
void t1_time() interrupt 3
{ uc shan,beep_stop;
th1=0x4b;
tl1=0xff;
shan++;
if(shan==10)
{ shan=0;
set_shan=~set_shan;
if((fin_flag)||(timing)) //当反向计数完成时 或计时时间到时
{ beep_stop++;
beep=~beep;
if(beep_stop==10)
{ fin_flag=0;
timing=0;
num[4]=0;num[5]=0;num[6]=0;num[7]=0;
beep_stop=0;
beep=1;}
}
}
}
2.4软件仿真
为了使电子数字秒表能实现单片机内部存储器eeprom,可以存储十组数据。数码管前两位显示分钟,后两位显示秒。正计时、倒计时可以切换。倒计时结束蜂鸣器报警,倒计时时间可设置。可以设置闹钟,查看记录的数据,暂停,清零等功能。用keil c51软件编辑c语言程序并且编译调试,在编写程序和编译调试的过程中出现了很多问题。在编写程序的时候将数码管显示的子程序和中断漏写了,导致程序不能编译成功。在编写程序是将特殊符号弄错或漏写,在编程时最容易出现的就是将“;”漏写和将“,”和“、”弄错,以至程序不能正常编译。
2.5软硬件仿真
用keil c51软件编辑c语言程序,将编写好的c语言程序编译成功后生成hex代码,供下载器使用。使用proteus isis绘制原理图,将keil c51和proteus isis连接起来调试,进行仿真。当按下k1键时,电子数字秒表开始计时,如果想要对时间进行调整,可以通过调整设置模块来实现。当按下k2键时,可以存储数据,每按一次存储一组数据,能存储最近十组数据。如想要倒计时可以按下k5键来调节倒计时的秒数,倒计时结束时蜂鸣器响五声后停止。如想要切换到正计时可以按下k4键,同时k5键还可以调闹钟,闹钟时间到时,蜂鸣器响五声数码管闪五下停止。如果想要退出重新计时就再按一下k6即可复位。
结 论
在整个设计过程中软件方面借助各个渠道的资料,主要设计了正计时程序、倒计时程序、 设置时间程序、倒计时蜂鸣器提示程序以及lcd显示程序;系统的调试主要是通过一块at89s51开发板,再借助于keil、stc以及少许自己搭建的外围电路实现的;再此过程中,分步调试时显示出了正计时、倒计时、数据存储以及倒计时蜂鸣器提示,集中调试时没有达到预期效果。此电子数字秒表具有读显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。
在整个设计过程中学到了许多没学到的知识,在电路焊接时虽然没什么大问题,但从中也知道了焊接在整个作品中的重要性,电路工程量大,不能心急,一个个慢慢来不能急于求成。反而达到事半功倍的效果。对电路的设计、布局要先有一个好的构思,才显得电路板美观、大方。程序编写中,由于思路不清晰,开始时遇到了很多的问题,经过静下心来思考,理清了思路,反而得心应手。
从这次的论文设计中,我真正的体会到,知识的重要性,特别是要理论联系实际,把我们所学的理论知识运用到实际生活当中,要用知识改变一切。
致 谢
历时将近两个月的时间终于将这篇论文写完,在论文的写作过程中遇到了无数的困难和障碍,都在同学和老师的帮助下度过了。尤其要强烈感谢我的论文指导老师—邓明元老师,他对我进行了无私的指导和帮助,不厌其烦的帮助进行论文的修改和改进。另外,在校图书馆查找资料的时候,图书馆的老师也给我提供了很多方面的支持与帮助。在此向帮助和指导过我的各位老师表示最中心的感谢!感谢这篇论文所涉及到的各位学者。本文引用了数位学者的研究文献,如果没有各位学者的研究成果的帮助和启发,我将很难完成本篇论文的写作。感谢我的同学和朋友,在我写论文的过程中给予我了很多的素材。