基于51单片机的多功能抢答器微机原理实验报告Word文档下载推荐.docx
《基于51单片机的多功能抢答器微机原理实验报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《基于51单片机的多功能抢答器微机原理实验报告Word文档下载推荐.docx(17页珍藏版)》请在冰豆网上搜索。
![基于51单片机的多功能抢答器微机原理实验报告Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2022-11/23/c5f20193-fbe4-4a29-a34d-73978b8af621/c5f20193-fbe4-4a29-a34d-73978b8af6211.gif)
此次设计提出了用AT89C51单片机为核心控制元件,设计一个简易的抢答器,本方案以AT89C51单片机作为主控核心,与晶振、数码管、蜂鸣器等构成八路抢答器,利用了单片机的延时电路、按键复位电路、时钟电路、定时/中断等电路,设计的八路抢答器具有实时显示抢答选手的号码和抢答时间的特点,还有复位电路,使其再开始新的一轮的答题和比赛,同时还利用C51语言编程,使其实现一些基本的功能。
本设计的系统实用性强、判断精确、操作简单、扩展功能强。
它的功能实现是比赛开始,主持人读完题之后按下总开关,即计时开始,此时数码管开始进行20s的倒计时,直到有一个选手抢答时,对应的会在数码管上显示出该选手的编号和抢答所用的时间,如果在规定的20s时间内没有做出抢答,则此题作废,即开始重新一轮的抢答。
在抢答和回答时间的最后5s,蜂鸣器都会给予报警提示。
功能介绍主持人按“抢答开始”键,立刻进入抢答倒计时(预设20S抢答时间),如有选手抢答,会有提示,并会显示其号数,不进行抢答查询,所以第一个按抢答的选手有效。
倒数时间到小于5S会每秒响一下提示音。
如倒计时期间,主持人想停止倒计时可以随时按“停止”按键,系统会自动进入准备状态,等待主持人按“抢答开始”进入下次抢答计时。
如果主持人未按“抢答开始”键,则无法按抢答按键。
五、硬件设计各模块的选择和论证
5.1控制器选择
控制器主要用于对显示、抢答、音乐、计分等模块进行控制。
采用ATMEL公司的AT89S51作为系统控制器的CPU方案。
单片机算术运算功能强,软件编程灵活、自由度大,可以用软件编程实现各种算法和逻辑控制,并且由于其功耗低、体积小、技术成熟和成本低等优点,使其在各个领域应用广泛。
5.2键盘选择
键盘是单片机不可缺少的输入设备,是实现人机对话的纽带。
键盘按结构形式可以分为非编码键盘和编码键盘,前者用软件方法产生键码,而后者则用硬件方法来产生键码。
在单片机中使用的都是非编码键盘,因为非编码键盘结构简单,成本低廉,非编码键盘的类型很多,常用的有独立式键盘,行列式键盘等。
本设计采用独立式键盘
键盘接口中使用多少根I/O线,键盘中就有几个按键,键盘接口使用了8根I/O口线,该键盘就有8个按键,这种类型的键盘,其按键比较少,且键盘中各按键的工作互不干扰。
因此可以根据实际需要对键盘中的按键灵活的编码。
如图2-2。
最简单的编码方式就是根据I/O输入口所直接反映的相应按键,按下的状态进行编码,称按键直接状态码,对于这样编码的独立式键盘,CPU可以通过直接读取I/O口的状态来获取按键的直接状态编码值,根据这个值直接进行按键识别,这样形式的键盘结构简单,按键识别容易。
独立式键盘的缺点是需要占用比较多的I/O口线,当单片机应用系统键盘中需要的按键比较少或I/O口线比较富余时,可以采用这样类型的键盘。
A
图2-2独立式键盘
5.3时钟频率电路的设计
单片机必须在时钟的驱动下才能工作。
在单片机内部有一个时钟振荡电路,只需要外接一个振荡源就能产生一定的时钟信号送到单片机内部的各个单元,决定单片机的工作速度。
时钟电路如下图所示。
图2-5外部振荡源电路
一般选用石英晶体振荡器。
此电路在加电大约延迟10ms后振荡器起振,在XTAL2引脚产生幅度为3V左右的正弦波时钟信号,其振荡频率主要由石英晶振的频率确定。
电路中两个电容C1,C2的作用有两个:
一是帮助振荡器起振;
二是对振荡器的频率进行微调。
单片机在工作时,由内部振荡器产生或由外直接输入的送至内部控制逻辑单元的时钟信号的周期称为时钟周期。
其大小是时钟信号频率的倒数。
图中时钟频率为12MHz。
5.4复位电路的设计
单片机的第9脚RST为硬件复位端,只要将该端持续4个机器周期的高电平即可实现复位,复位后单片机的各状态都恢复到初始化状态,其电路图如下所示:
5.5报警电路
我们知道,声音的频谱范围约在几十到几千赫兹,若能利用程序来控制单片机某个口线的“高”电平或低电平,则在该口线上就能产生一定频率的巨型波,接上喇叭就能发出一定频率的声音,若再利用延时程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调,使喇叭发出不同的声音。
本文设计如下图所示。
图中单片机的14脚输出具有复合功能,此处用到了单片机14脚的IO端口功能,单片机通过内部定时器的操作实现交替变换的波形输出驱动扬声器发声。
5.6发声电路抢答器显示模块选择
显示模块主要是显示抢答的时间,组别号码等。
在使用传统的数码管显示。
数码管具有:
低能耗、低损耗、低压、寿命长、耐老化、防晒、防潮、防火、防高(低)温,对外界环境要求低,易于维护,同时其精度高,称量快,精确可靠,操作简单。
数码显示是采用BCD编码显示数字,程序编译容易,资源占用较少。
显示功能与硬件关系极大,当硬件固定后,如何在不引起操作者误解的前提下提供尽可能丰富的信息,全靠软件来解决。
在这里我们使用的是七段数码管显示,通常在显示上我们采用的方法一般包括两种:
一种是静态显示,一种是动态显示。
其中静态显示的特点是显示稳定不闪烁,程序编写简单,但占用端口资源多;
动态显示的特点是:
显示稳定性没静态好,程序编写复杂,但是相对静态显示而言占用端口资源少。
在本设计中根据实际情况采用的是动态显示方法。
4位七段数码管显示电路如下图所示。
图2-14位七段数码管显示电路图
上图中数码管采用的是4位一体七段共阳数码管,其中A~H段分别接到单片机的P0口,由单片机输出的P0口数据来决定段码值,位选码COM1,COM2,COM3,COM4分别接到单片机的P2.0,P2.1,P2.2,P2.,3,由单片机来决定当前该显示的是哪一位。
在图中还有一个排阻,连接在P0口上,用作P0口的上拉电阻,保证P0口没有数据输出时候处于高电平状态。
通过查表法,将其在数码管上显示出来,其中P0口为字型码输入端,P2口低4位为字选段输入段。
在这里我们通过查表将字型码送给7段数码管显示的数字。
数码显示管用来作为时间的显示输出,一般用7段数码显示管。
本次设计中采用7段共阳数码显示管应用简单、可靠性高、成本低,作为显示输出。
连接时段选信号接在P0口的P0.0~P0.7七个I/O口上,P1口是准双向I/O接口在输出驱动部分具有驱动4个TTL负载的能力,即输出电流不大于400μA,所以在接电阻时选择接10KΩ限流电阻。
而在位选方面采
用P2口的P2.0~P2.3用单片机四个I/O口作为位选信号的输出口。
5.7总电路图
六、抢答器的软件设计
系统软件由主程序和INT0中断服务组成。
主程序由验键,违规显示,倒计时等功能子程序组成,系统完成初始化后循环检查各个功能当用户使用某个功能时,按下相应的按钮(或开关)单片机进入相应的功能处理。
INT0中断服务程序完成抢答信号采样和识别处理。
该智能抢答器以AT89S52单片机为控制核心,控制精度较高,操作误差主要来自晶振自身所造成的误差。
其他外围电路包括复位电路、时钟电路、报警电路、LED显示电路、抢答按键等。
该智能抢答器具有计时记忆功能,一次时间设置完,复位后不需重新进行时间设定;
通过按键扫描输出按键信息,并通过单片机将它转化为在七段数码管上显示的字形符。
单片机的P1口为8组抢答按键的输入口,P0.0~P0.7为数码管的段选口,P2.0~P2.2为数码管的片选口。
P3.4为报警电路的控制口,P3.5为暂停按钮的控制口,P3.6为开始按钮的控制口,P3.7为复位按钮的控制口。
源程序
#defineuintunsignedint
#defineucharunsignedchar
/*-----------------------------------------------------------
共阴极数码管编码表0-f显示
------------------------------------------------------------*/
unsignedcharcodetable[]={0x40,0x79,0x24,0x30,0x19,
0x12,0x02,0x78,0x00,0x10,0x08,0x03,
0x46,0x21,0x06,0x0e};
变量定义
sbitstart=P3^6;
sbitstop=P3^5;
sbitreset=P3^7;
sbitkey1=P1^0;
sbitkey2=P1^1;
sbitkey3=P1^2;
sbitkey4=P1^3;
sbitkey5=P1^4;
sbitkey6=P1^5;
sbitkey7=P1^6;
sbitkey8=P1^7;
sbitbuzzer=P3^4;
bitstart_flag=0;
bitstop_flag=0;
bitkey1_flag=0;
bitkey2_flag=0;
bitkey3_flag=0;
bitkey4_flag=0;
bitkey5_flag=0;
bitkey6_flag=0;
bitkey7_flag=0;
bitkey8_flag=0;
bitreset_flag=0;
bitaction=0;
ucharsecond=15;
uchartimer0_count=0;
ucharnumber=0;
ucharnumber_display=0;
/*-----------------------延时函数--------------------------------------*/
voiddelay(uintz)
{
uintx,y;
for(x=z;
x>
0;
x--)
for(y=110;
y>
y--);
}
/*--------------数码管显示驱动函数-----------------------*/
voiddisplay(ucharnumber,ucharsecond)
ucharsecond_first,second_second;
second_first=second/10;
second_second=second%10;
P2=0xfe;
P0=table[number];
delay
(2);
P2=0xfd;
P0=0x3f;
P2=0xfb;
P0=table[second_first];
P2=0xf7;
P0=table[second_second];
/*----------------------------开始键扫描函数--------------------------------*/
voidstart_keyscan()
{if(start==0)
{delay(8);
if((start==0)&
&
(!
start_flag))
{
start_flag=1;
action=1;
TR0=1;
}
}
else
{
start_flag=0;
}
/*--------------------------------------八位抢答键扫------------------------------------------*/
ucharkey_scan8()
if(key1==0)
delay(8);
if((key1==0)&
key1_flag))
key1_flag=1;
number=1;
number_display=number;
key1_flag=0;
number=0;
if(key2==0)
if((key2==0)&
key2_flag))
key2_flag=1;
number=2;
key2_flag=0;
if(key3==0)
if((key3==0)&
key3_flag))
key3_flag=1;
number=3;
key3_flag=0;
if(key4==0)
if((key4==0)&
key4_flag))
key4_flag=1;
number=4;
key4_flag=0;
if(key5==0)
if((key5==0)&
key5_flag))
key5_flag=1;
number=5;
key5_flag=0;
if(key6==0)
if((key6==0)&
key6_flag))
key6_flag=1;
number=6;
key6_flag=0;
if(key7==0)
if((key7==0)&
key7_flag))
key7_flag=1;
number=7;
key7_flag=0;
if(key8==0)
if((key8==0)&
key8_flag))
key8_flag=1;
number=8;
key8_flag=0;
if(number_display!
=0)
return1;
return0;
/*--------------------复位键扫描函数-----------------------------------*/
voidreset_keyscan()
if(reset==0)
if((reset==0)&
reset_flag))
reset_flag=1;
number_display=0;
second=15;
reset_flag=0;
voidfengming()//蜂鸣函数,脉宽t=1ms周期T=2ms频率f=0.5khz实际发现延时1ms的时候效果最好
{//延时1ms
buzzer=0;
//给P3.7口送高电平
delay(100);
//延时1ms
buzzer=1;
delay(100);
/*-------------------主函数---------------------------*/
voidmain()
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=0;
while
(1)
{
start_keyscan();
reset_keyscan();
while(action==1)
{if(second<
=6&
second>
0)
fengming();
while(!
key_scan8()&
!
stop==0)
{
display(number_display,second);
if(second==0)
{
second=15;
break;
}
}
TR0=0;
display(number_display,second);
action=0;
break;
display(number_display,second);
/*-----------------------中断服务函数----------------------*/
voidtimer0()interrupt1
timer0_count++;
if(timer0_count==15)
timer0_count=0;
second--;
if(second<
if(second==0)
TR0=0;
action=0;
七、问题分析
数码管显示问题:
本次设计的最终方案是采用数码管显示屏实现显示功能,最初数码管显示不正常,出现闪烁现象。
通过调试发现这是由于延时时间选择不当会使人眼产生视觉暂留效果,每一次显示时都必须加入适当的时间延时。
由于一开始所选用的延时时间太短因此出现闪烁现象,在增加显示延时之后,数码管显示正常。
蜂鸣器异常启动问题:
蜂鸣器的启动/关闭是通过单片机输出的控制信号来实现的,当前时间与闹钟设置时间比较吻合时,单片机将对闹铃控制口执行取反命令,从而启动蜂鸣器发声。
一开始编写程序时,没有对控制口的最初状态作正确设置,由于系统开机复位后,闹铃控制口处于高电平状态,因此出现一开机蜂鸣器就处于启动状态的情况。
通过在主程序最开始加入对闹铃控制口取零命令后,蜂鸣器启动/关闭控制恢复正常。
8.体会
此实验利用protues仿真软件实现,基本实现了所要求的功能。
在本次实验中对单片机内部结构有一定了解,熟悉了各个引脚的功能,同时熟知了LED数码管的使用及各种电路的功能。
程序不要光看不写,一定要自己写一次。
最开始的时候,啥都不懂,可以抄人家的程序过来,看看每一句是干什么用的,达到什么目的,运行后有什么后果,看明白了之后,就要自己写一次,你会发现,原来看明白别人的程序很容易,但到自己写的时候却一句也写不出来,这就是差距。
本次试验主要是参考网上资料再加上自己理解部分修订所得,我觉得单片机课程设计很有必要,而且很有意义。
但当拿到题目时,确实不知道怎么着手,有些迷茫,上网查资料,问同学,在同学的帮助下,历时两个星期,解决一个又一个的困难,终于完成任务。
在这次课程设计中,运用到了很多现学微机的知识,如8255,本次用C语言程序实现算是很高的挑战,虽然过去从未独立应用过它们,但在学习的过程中带着问题去学我发现效率很高,这是我做这次课程设计的一大收获。
另外,要做好一个课程设计,就必须做到:
在设计程序之前,对所用单片机的内部结构有一个系统的了解,知道该单片机内有哪些资源;
要有一个清晰的思路和一个完整的的软件流程图;
在设计程序时,不能妄想一次就将整个程序设计好,反复修改、不断改进是程序设计的必经之路;
要养成注释程序的好习惯,一个程序的完美与否不仅仅是实现功能,而应该让人一看就能明白你的思路,这样也为资料的保存和交流提供了方便;
在设计课程过程中遇到问题是很正常,但我们应该将每次遇到的问题记录下来,并分析清楚,以免下次再碰到同样的问题的课程设计结束了,但是从中学到的知识会让我受益终身。
发现、提出、分析、解决问题和实践能力的提高都会受益于我在以后的学习、工作和生活中。
设计过程,好比是我们人类成长的历程,常有一些不如意,但毕竟这是第一次做,难免会遇到各种各样的问题。
在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,不能灵活运用。
不过这次课设总算通过自己的努力得以实现,所谓过