秒表课程设计.docx
《秒表课程设计.docx》由会员分享,可在线阅读,更多相关《秒表课程设计.docx(19页珍藏版)》请在冰豆网上搜索。
秒表课程设计
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)晶振电路
3)EA处理
4)电源设计
原理图如下:
2.3秒表时间显示电路设计
2.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仿真软件的应用,使我们在没有硬件开销的情况下,更快更好的接触到单片机的开发和应用,并且方便了程序的调试。
Proteus仿真图参见——附2系统原理图。
5设计体会
经过这六周的单片机实训,自己有很多的心得体会,我接触单片机程序设计将近有一年了,第一次接触是跟着电气开发部一起学习,其实当时也没学到太多内容,只是懂得了一点皮毛而已。
而现在做一个相对自己水平来说功能较强的实物,这使我在实践中对单片机的理解又加深了不少,而且,在这个课程设计中,让我真真切切感受到收获的喜悦。
在做的过程中,我遇到了很多问题,通过自己的努力,比如上网查资料,去图书馆借书,或者请教高年级的同学,都把他们一一解决了,成功后的喜悦给了我莫大学好单片机的信心和动力。
单片机对于我们电专业的学生来说是一门很重要的学科,老师和一些毕业的学长都说,如果学好单片机,就凭这门技术找一个好工作不成问题。
尽管我们在课堂上学到的内容有限,但在以后还要好好的学习单片机。
最后感谢老师对我们的精心指导和帮助,感谢同学们对我的帮助。
下面我就来谈谈我个人的几点体会:
1.在设计程序时,不能妄想一次就将整个程序设计好,“反复修改,不断改进”是程序设计的必经之路。
2.要养成注释程序的好习惯,一个程序的完美与否不仅仅是实现功能,而应该让人一看就能明白你的思路,这样也为资料的保存和交流提供了方便。
3.在设计程序过程中遇到问题是很正常的,但我们应该将每次遇到的问题记录下来,并分析清楚,以免下次再碰到同样的问题。
4.在设计程序时,将自己的程序分成一个模块一个模块来写,先写程序的主体,编译没错误后再往上添加其他功能模块,添加一个功能模块就编译一次,并下载到单片机里查看是否有错误,等成功后再依次添加其他模块直至完成所有功能。
参考文献
【1】贾宗璞,许合利.C语言程序设计:
中国矿业大学出版社,2007
【2】靳孝峰,王艳.单片机的原理与应用,北京:
北京航空航天大学大学出版社2009
【3】康华光.电子技术基础(模拟部分)(第五版).北京:
高等教育出版社,2006.
附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:
系统原理图