LED数码管秒表.docx
《LED数码管秒表.docx》由会员分享,可在线阅读,更多相关《LED数码管秒表.docx(26页珍藏版)》请在冰点文库上搜索。
LED数码管秒表
单片机课程设计说明书
课题名称
专业
电气工程
学生姓名
班级
学号
指导教师
完成日期
2012年6月10日
1概述----------------------------------------------------------------3
1.1总体设计方案------------------------------------------3
1.2硬件设计与焊接----------------------------------------3
1.3软件设计方案------------------------------------------3
2系统总体方案及硬件设计----------------------------------4
2.1硬件总体设计------------------------------------------4
2.2单片机基本电路设计------------------------------------6
2.3秒表时间显示电路设计----------------------------------7
2.4独立按键电路设计--------------------------------------9
2.5蜂鸣器电路设计---------------------------------------10
3软件设计-------------------------------------------------11
3.1程序设计思路-----------------------------------------11
3.2秒表程序构成-----------------------------------------11
3.3源程序代码与流程图-----------------------------------12
4实验仿真-------------------------------------------------14
5设计总结-------------------------------------------------15
附录1-----------------------------------------------------------------16
附录2-----------------------------------------------------------------22
附录3-----------------------------------------------------------------23
1概述
1.1总体设计方案
先进行系统板的基本焊接,即先将晶振电路和复位电路焊接完成。
然后对秒表的功能进行总体的设计和规划,列写出程序的纲要,规划好I/O口的控制对象。
再进行外围电路的设计,根据安排好的I/O口的使用,设计出合理的电路图,并进行最后的焊接。
最后,根据自己的总体设计和规划进行软件设计。
1.2硬件设计与焊接
最小系统版是现成的套件,只要焊接时细心一点基本不会出错,而数码管一般是由P0和P2口控制,或者由P0口加锁存器控制,这也不需要自己过多的去设计,只要焊接时仔细一点,一般也不会出错。
在这个秒表中,最重要的就是独立按键的设计和焊接,因为,如果设计不合理,就很有可能造成秒表的操作不便或者是计时误差增大。
我认为,按键2控制外部中断0是最优选择。
1.3软件设计方案
将各个功能以模块化的形式设计出来,当然,要先写主体,编译通过并下载入实验板功能可以实现后再添加其他功能模块,然后再编译下载,一步一步直至完成所有功能。
软件设计要比硬件设计复杂很多,出现的问题也多。
小问题一大堆,。
在设计中,我遇到的最大的两个问题就是存储时间的数组定义和减小按键存数时产生的误差。
刚开始我存储时间数组定义为code型,结果不能用设置的时间变量赋值,在网上找了好久才发现问题所在,只能将code去掉;最初存储时间数值的按键只是一个单纯的按键,结果发现按键按下期间秒表是停止的,最后只得将该功能用外部中断来实现,并且将其设置为下降沿触发,这样就大大减少了误差。
2系统总体方案及硬件设计
2.1硬件总体设计
1)单片机选型:
AT89S51
2)复位电路:
上电+按钮
3)晶振电路
4)键盘:
独立键盘+中断
5)数码管显示:
LED
6)独立按键控制
原理图如下:
单片机管脚图:
2.2单片机基本电路设计
1)复位电路:
上电+按钮
2)晶振电路
原理图如下:
2.3秒表时间显示电路设计
1)4位7段LED数码管(共阴)
2)排阻
3)1kΩ电阻*4
4)S9012PNP三极管*4
为了不使LED数码管过流损坏,用上拉排阻限流。
LED数码管位选直接与P2口相连,数码管显示会比较暗,为了解决这个问题,我从网上找到利用S9012PNP三极管作为驱动的方法来解决这个问题!
七段LED数码管及其接口
七段LED数码管由七个发光段构成,每段均为1个LED二极管。
通过控制不同段的点亮和熄灭,显示出16进制数字或字符。
七段LED显示器有共阳极和共阴极两种结构,如图所示的七段LED实际上包含8个LED(7段字形加上小数点DP)。
1位LED显示器有1根位选线和8根段选线,段选线控制字符的选择,位选线控制显示位的亮和暗。
十六进制数及空白字符与数码管的显示段码
字型
共阳级段码
共阴极段码
字型
共阳级段码
共阴极段码
0
C0H
3FH
9
90H
6FH
1
F9H
06H
A
88H
77H
2
A4H
5BH
B
83H
7CH
3
B0H
4FH
C
C6H
39H
4
99H
66H
D
A1H
5EH
5
92H
6DH
E
86H
79H
6
82H
7DH
F
84H
71H
7
F8H
07H
空白
FFH
00H
8
80H
7FH
P
8CH
73H
4位LED数码管(共阴)管脚图:
原理图如下:
2.4独立按键电路设计
参考市场上的秒表,一般都有清零、开始计时和查看计时记录的功能,所以我用4个按钮来实现清零/查看、开始/计时、上翻、下翻的功能,这样我的秒表基本上和市场上的秒表功能一致。
原理图如下:
2.5蜂鸣器电路设计
当用户按下任意有效按键时蜂鸣器都会发出蜂鸣提醒,以提示用户按键成功,已进入既定程序进行工作,从而提升该秒表系统的用户体验。
原理图如下:
3软件设计
3.1程序设计思路
利用定时器经确定时,并且利用随机存储区的有限空间,定义一个二维数组,通过按键将时间数值赋给数组(实践证明,随机存储器内最多只能存储30组时间数值),然后在秒表停止或在数组存满的情况下将所存的时间数值读出。
当然,也需要通过按键来读取不同时间数值,并且使用按键来控制秒表的开始、停止与清零。
附加项目:
1)按键每按下一次,蜂鸣器声响50毫秒或100毫秒;
2)在秒表启动时,第二段数码管小点亮0.5毫秒,灭0.5毫秒;
3)在秒表启动和读取所存时间数值时,由于只有四段数码管,不可能将分,秒,毫秒同时显示,所以在秒表启动时,当时间小于60秒时,数码管显示秒和毫秒,而大于60秒时则显示分和秒;在读取所存时间数值时,采用“点”作标志位,第二段数码管的“点”亮表示显示的是秒和毫秒,而第四段的数码管的“点”亮则表示的是分和秒。
3.2秒表程序构成
(具体程序参见附1)
3.2.1主程序(main函数)
程序的初始入口,不断调用各个子程序,程序的骨架。
3.2.2秒表启动存数程序(keeptime函数)
用以处理分,秒和毫秒之间的联系。
3.2.3读取所存数值处理程序(showtime函数)
用以读取处理所存时间数值并加以处理。
3.2.4数码管显示程序
1)秒表启动时显示程序(display函数):
确定显示数值,将显示数值分为个位、十位、百位、千位,分别查表显示。
2)读取所存时间数值显示程序(display2函数):
调取数组值赋给该函数,确定显示数值,将将其分为个、十、百、千位,分别查表显示。
3)所存时间数值序号显示程序(display3函数):
用以显示所存时间的序号,以便于区分。
3.2.5按键扫描程序
1)扫描按键1(scankey1函数)
用于停止秒表或所存时间数值清零。
2)扫描按键2(exter0函数)
用以触发外部中断0,触发方式为下降沿触发,尽量降低了存储时间数值时引起的误差。
3)扫描按键3(scankey3函数)
用于所存时间数值的序号加一。
4)扫描按键3(scankey4函数)
用于所存时间数值的序号减一。
3.2.6延时程序(delay函数)
用于延时z*1毫秒。
3.3源程序代码与流程图
见附录1
程序框图:
计时程序流程图:
时间存储程序、时间查看程序流程图略
4实验仿真
单片机学习中我们使用proteus做仿真,该软件的优点是可以搭建单片机的常用仿真电路,并且可以利用丰富的外设器件,如数码管,LCD,按键,传感器,A/D,D/A等,实现与实际系统板运行相接近的效果,即可以完成系统级的调试。
使用Proteus软件进行单片机系统仿真设计,是虚拟仿真技术和计算机多媒体技术相结合的综合运用,有利于培养学生的电路设计能力及仿真软件的操作能力;在单片机课程设计中,我们使用Proteus开发环境学习,在不需要硬件投入的条件下,对单片机的学习比单纯学习书本知识更容易接受,更容易提高。
实践证明,在使用Proteus进行系统仿真开发成功之后再进行实际制作,能极大提高单片机系统设计效率。
Proteus仿真软件可以看做是构建了一个特殊的单片机系统,只要将所写程序的HEX文件导入该单片机系统,就可以让它一句句的执行所写的指令,也可以让它与Keil实现联调,程序有问题可以随时改,帮助快速调试程序。
Proteus仿真软件的应用,使我们在没有硬件开销的情况下,更快更好的接触到单片机的开发和应用,并且方便了程序的调试。
5设计总结
我认为单片机本来就是一门应用大于理论、实践大于书本的课程,所以能够有这样一次单片机的课程设计实在是太好了!
特别是让我们自己动手制作成品电路,自己动脑编写程序,自己发现自己的不足,自己改正错误。
在本次课程设计中,我遇到了困难!
编写程序,如何让用户知道你这个东西是用来干嘛的?
比如我设计的是一个秒表,在显示的问题上,我一开始设计的是以秒的单位符号作为秒和毫秒的分界,但是经过老师的指导发现并不是大多数人所能理解的,相当一部分人会认为这位的数码管出现了乱码,老师指正后我改为以小数点做为分界,不但让用户更清楚的辨认,而且还引入了分的计时,更加完善了秒表的功能。
实际电路,如何让实际电路更符合实际的使用需求?
我一开始连的电路板,没有加上S9012PNP三极管作为驱动电路,4位数码管显示的数字略显暗淡,用户在白天阳光下很难辨认清楚,于是在网上发现了用S9012PNP三极管做驱动的办法加以解决,加上了S9012PNP三极管后数码管显示问题改善了,数字显示明亮了。
S9012PNP三极管作为驱动在共阳极数码管上有显著的作用,在共阴极数码管上的效果没有共阳极的好。
通过这次课程设计让我对单片机的应用有了更深层次的了解,也加深了对单片机的兴趣,我想在日后的学习生活工作中我也能基本的运用单片机这一手段来做一些基本的电气电路设计了。
参考文献:
【1】陈益飞.单片机原理及应用技术.北京:
国防工业出版社,2011.
【2】康华光.电子技术基础(模拟部分)(第五版).北京:
高等教育出版社,2006.
【3】彭伟.单片机C语言程序设计实训100例.北京:
电子工业出版社,2009.
附录1:
源程序代码:
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitbuz=P3^0;
sbitkey1=P3^1;
sbitkey2=P3^2;
sbitkey3=P3^3;
sbitkey4=P3^4;
ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
ucharbank[30][3]={0};
ucharmin,sec,msec,aa,bb,cc,dd,ee,ff;
uchartab=0,tab1=0,i,j;
uinttab3;
voiddisplay(ucharqian,ucharbai,ucharshi,ucharge);
voiddisplay2(ucharqian,ucharbai,ucharshi,ucharge,ucharqq);
voiddisplay3(ucharshi,ucharge);
voiddelay(uint);
voidscankey1();
voidscankey3();
voidscankey4();
voidkeeptime();
voidshowtime();
voidinit()//初始化子程序
{
for(i=0;i<30;i++)
for(j=0;j<3;j++)
bank[i][j]=0;
P3=0xff;
min=0;
sec=0;
msec=0;
TMOD=0X01;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
EX0=1;
IT0=1;
ET0=1;
TR0=tab1;
tab=0;
tab3=1;
i=0;
}
voidmain()//主函数
{
init();
while
(1)
{
scankey1();
if(tab1==1)
keeptime();
else
showtime();
}
}
voiddisplay(ucharqian,ucharbai,ucharshi,ucharge)//显示子程序1,用于秒表走动时显示
{
P2=0xfe;
P0=table[qian];
delay
(1);
P0=0;
P2=0xfd;
if(tab<=50)
P0=table[bai]|0x80;
elseP0=table[bai];
delay
(1);
P0=0;
P2=0xfb;
P0=table[shi];
delay
(1);
P0=0;
P2=0xf7;
P0=table[ge];
delay
(1);
P0=0;
}
voiddisplay2(ucharqian,ucharbai,ucharshi,ucharge,ucharqq)//显示子程序2,显示所存时间
{
P2=0xfe;
P0=table[qian];
delay
(1);
P0=0;
P2=0xfd;
if(qq==0)
P0=table[bai]|0x80;
elseP0=table[bai];
delay
(1);
P0=0;
P2=0xfb;
P0=table[shi];
delay
(1);
P0=0;
P2=0xf7;
if(qq==1)
P0=table[ge]|0x80;
elseP0=table[ge];
delay
(1);
P0=0;
}
voiddisplay3(ucharshi,ucharge)//显示子程序3,显示存储时间的序号
{
P2=0xfb;
P0=table[shi];
delay
(1);
P0=0;
P2=0xf7;
P0=table[ge];
delay
(1);
P0=0;
}
voidkeeptime()//秒表记时函数
{
msec=tab;
aa=msec%10;
bb=msec/10;
cc=sec%10;
dd=sec/10;
ee=min%10;
ff=min/10;
if(tab==100)
{
tab=0;
sec++;
}
if(sec==60)
{
sec=0;
min++;
}
if(min==59)
{
tab1=0;
TR0=tab1;
}
if(min==0)
display(dd,cc,bb,aa);
if(min!
=0)
display(ff,ee,dd,cc);
}
voidshowtime()//存储时间调出显示函数
{
ucharpp;
pp=(tab3-1)/2;
scankey3();
scankey4();
aa=bank[pp][0]%10;
bb=bank[pp][0]/10;
cc=bank[pp][1]%10;
dd=bank[pp][1]/10;
ee=bank[pp][2]%10;
ff=bank[pp][2]/10;
if(bank[0][0]==0)
display(0,0,0,0);
else
{
if(tab3%2==1)
display3((pp+1)/10,(pp+1)%10);
if(tab3%2==0)
{
if(bank[pp][2]==0)
display2(dd,cc,bb,aa,0);
if(bank[pp][2]!
=0)
display2(ff,ee,dd,cc,1);
}
}
}
voidscankey1()//检测按键1是否被按下
{
if(key1==0)
{
delay(8);
if(key1==0)
{
if(tab1==1)
{
tab1=0;
TR0=tab1;
}
else
{
init();
}
buz=0;
delay(100);
buz=1;
while(key1!
=1);
delay(8);
while(key1!
=1);
}
}
}
voidscankey3()//检测按键3是否被按下
{
if(key3==0)
{
delay(8);
if(key3==0)
{
if((tab3<60)&&(tab1==0))
tab3++;
buz=0;
delay(100);
buz=1;
while(key3!
=1);
delay(8);
while(key3!
=1);
}
}
}
voidscankey4()//检测按键4是否被按下
{
if(key4==0)
{
delay(8);
if(key4==0)
{
if((tab3>1)&&(tab1==0))
tab3--;
buz=0;
delay(100);
buz=1;
while(key4!
=1);
delay(8);
while(key4!
=1);
}
}
}
voiddelay(uintz)//延时函数
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voidexter0()interrupt0//外部中断0函数
{
delay(10);
if((key2==0)&&(i<30))
{
if(tab1==0)
{
tab1=1;
TR0=tab1;
}
else
{
j=0;
bank[i][j++]=msec;
bank[i][j++]=sec;
bank[i][j]=min;
i++;
}
buz=0;
delay(50);
buz=1;
}
}
voidtimer0()interrupt1//定时器中断0函数
{
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
tab++;
}
附录2:
Proteus仿真:
附录3:
实物图:
初始状态
计时状态
查看状态