资源描述
目 录
摘 要 4
1 绪论 5
2 方案选择和论证 6
2.1 抢答器显示模块 6
2.2 控制器模块 6
2.3 电源方案的选择 7
3 硬件电路设计 7
3.1.基于AT89S52单片机八路抢答器的硬件设计 7
3.1.1系统整体方案的设计 7
3.1.2 系统硬件组成 8
3.1.3复位电路设计 8
3.1.4外部晶振时钟电路设计 9
3.1.5 键盘及读数原理 10
3.1.6 显示模块电路设计 11
3.1.7蜂鸣器报警电路设计 11
4 抢答器的软件设计 13
4.1 数码显示软件设计 14
4.2 定时器中断软件设计 14
5 电路的调试 15
5.1电路模块调试 15
5.2 软件调试的基本方法 16
5.3 软件调试问题分析 16
致谢 17
参考文献 18
附件1:源程序代码 19
八路抢答器的设计与报告
摘要: 电子智能抢答器在抢答过程中,为了知道哪一组或哪一位选手先答题,必须要设计一个系统来完成这个任务。如果在抢答中,靠视觉是很难判断出哪组先答题。利用单片机系统来设计抢答器,使以上问题得以解决,即使两组的抢答时间相差几微秒,也可分辨出哪组优先答题。本设计使用AT89S52单片机来设计智能抢答器,组数可以在八组以内任意使用。并且具有倒计时和报警功能。利用AT89S52单片机对信号进行锁存、显示等功能。分别从硬件和软件两方面阐述了该控制系统的设计方法,并经过调试和运行使该系统达到预期目标,具有反应快、功能齐全、实用性强的特点。
键词:AT89S52 显示 抢答
17
绪论
随着微电子技术、电力电子技术、传感器技术、永磁材料技术、自动控制技术、微机应用技术的发展,使单片微型计算机也得到迅速的发展,单片机微型计算机是微型计算机的一个重要分支,也是颇具生命力的机种。单片机微型计算机简称单片机,特别适用于控制领域,故又称为微控制器。
单片机(单片微型计算机)的应用已经渗透到国民经济的各个部门和领域,它起到了越来越重要的作用。单片微型计算机就是将中央处理单元、存储器、定时/计数器和多种接口都集成到一块集成电路芯片上的微型计算机。因此一块芯片就构成了一台计算机。它已成为工业控制领域、智能仪器仪表、尖端武器、日常生活中最广泛使用的计算机。它作为嵌入式控制系统的主体与核心,代替了传统的控制系统的常规电子线路。同时楼宇智能化的发展与成熟,也为基于单片机的照明控制系统的普及与应用奠定了坚实的基础。
系统设计主要包括硬件和软件两大部分,依据控制系统的工作原理和技术性能,将硬件和软件分开设计。硬件设计部分包括电路原理图、合理选择元器件、绘制线路图,然后对硬件进行调试、测试,以达到设计要求。软件设计部分,首先在总体设计中完成系统总框图和各模块的功能设计,拟定详细的工作计划;然后进行具体设计,包括各模块的流程图,选择合适的编程语言和工具,进行代码设计等;最后是对软件进行调试、测试,达到所需功能要求。
在系统设计中设计方法的选用是系统设计能否成功的关键。硬件电路是采用结构化系统设计方法,该方法保证设计电路的标准化、模块化。硬件电路的设计最重要的选择用于控制的单片机,并确定与之配套的外围芯片,使所设计的系统既经济又高性能。硬件电路设计还包括输入输出接口设计,画出详细电路图,标出芯片的型号、器件参数值,根据电路图在仿真机上进行调试,发现设计不当及时修改,最终达到设计目的。软件设计的方法与开发环境的选取有着直接的关系,本系统由于是采用51系列单片机,采用C语言编写程序。系统软件设计采用模块化系统设计方法,先编写各个功能模块子程序,然后进行组合与调整,经过调试后,达到设计功能要求。
2方案选择和辩论
2.1抢答器显示模块
显示模块主要是显示抢答的时间。我考虑有以下两种显示方案。
方案1:使用液晶屏显示时间。液晶显示屏(LCD)具有轻薄短小、低耗电量、无辐射危险,平面直角显示以及影像稳定不闪烁等优势,可视面积大,画面效果好,分辨率高,抗干扰能力强的特点。但由于只需要显示时间和组别的数字,信息量比较少,且由于液晶是以点阵的模式显示各种符号,需要利用控制芯片创建字符库,编程工作量大,控制器的资源占用较多,其成本也偏高。在使用时,不能有静电干扰,否则易烧坏液晶显示芯片,不易维护。
方案2:使用传统的数码管显示。数码管具有:低能耗、低损耗、低压、寿命长、耐老化、防晒、防潮、防火、防高(低)温,对外界环境要求低,易于维护,同时其精度高,称量快,精确可靠,操作简单,程序编译容易,资源占用较少。
根据以上的论述,采用方案二。
2.2 控制器模块
控制器主要用于各模块控制显示、抢答、音乐等。控制器的选择有以下两钟方案。
方案1:采用FPGA(现场可编程门列阵)作为系统的控制器。FPGA可以实现各种复杂的逻辑功能,规模大,密度高,它将所有器件集成在一块芯片上,减小了体积,提高了稳定性,并且可以应用EDA软件仿真、调试,易于进行功能扩展。FPGA采用并行的输入输出方式,提高了系统的处理速度,适合作为大规模实时系统的控制核心。但由于本设计对数据处理的速度要求不高,FPGA的高速处理的优势得不到充分体现,并且由于其集成度高,使其成本偏高,同时由于芯片的引脚较多,实物硬件电路板布线复杂,加重了电路设计和实际焊接的工作。
方案2:采用ATMEL公司的AT89S52作为系统控制器的CPU方案。单片机算术运算功能强,软件编程灵活、自由度大,可以用软件编程实现各种算法和逻辑控制,并且由于其功耗低、体积小、技术成熟和成本低等优点,使其在各个领域应用广泛。
基于以上分析拟订方案二。
2.3 电源方案的选择
系统需要多个电源,AT89S52使用5V稳压电源,四联数码管供电电压为5V。给出以下两个方案。
方案1:采用升压型稳压电路。用两片MC34063芯片分别将3V的电池电压进行直流崭波调压,得到5V稳压输出。只需使用两节电池,既节省了电池,又减小系统体积重量但该电路供电电流小,供电时间短,无法使相对庞大的系统稳定运作。
方案2:由于所做的设计不需要很高的精度要求,结合这个电源分析只要给系统5V的电压基本能输出显示和运用抢答,故只需利用一节5V的手机充电器便可使整个电路工作。该方法方便简单,节省材料。
综上所述,选择方案二。
3.1.基于AT89S52单片机八路抢答器的硬件设计
3.1.1系统整体方案的设计
本设计使用到的元器件包括:AT8952芯片、数码LED显示器
a. 抢答器同时供8名选手或8个代表队比赛,分别用8个按钮S1 ~ S8表示。
b. 抢答器具有锁存与显示功能。即选手按动按钮,锁存相应的编号,并在LED数码管上显示,同时扬声器发出报警声响提示。选手抢答实行优先锁存,优先抢答选手的编号一直保持到系统复位为止。
c. 抢答器具有定时抢答功能,且一次抢答的时间由主持人设定(如30秒),定时器进行减计时。
d. 参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号。
e. 如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,定时显示器上显示0。
3.1.2 系统硬件组成
根据系统框图和设计方案本文硬件电路主要分成三个部分;第一部分为按键组成的输入模块,第二部分为以AT89S52为核心的控制模块,第三部分由LED数码管和发光二极管组成的显示模块,第四部分由蜂鸣器组成的报警模块。
MCU
键盘部分
复位电路
外部晶振电路
蜂鸣器
数码管部分
图3-2 系统硬件组成
3.1.3复位电路设计
AT89S52的复位输入引脚RST为单片机提供了初始化的手段,可以使程序从指定处开始执行,在AT89S52的时钟电路工作后,只要RST引脚上出现超过两个机器周期以上的高电平时,即可产生复位的操作,只要RST保持高电平,则AT89S52循环复位,只有当RET由高电平变成低电平以后,AT89S52才从0000H地址开始执行程序,本系统采用按键复位方式的复位电路。
图3-3 复位电路
3.1.4外部晶振时钟电路设计
AT89S52的时钟可以由两种方式产生,一种是内部方式,利用芯片内部的振荡电路;另外一种为外部方式,本论文根据实际需要和简便,采用内部振荡方式,MCS-51内部有一个用于构成振荡器的高增益反相放大器,引脚XTAL1和XTAL2分别是此放大器的输入端和输出端,这个放大器与作为反馈元件的片外晶体或陶瓷谐振器一起构成了一个自激振荡器。
AT89S52虽然有内部振荡电路,但要形成时钟,必须外接元件,所以实际构成的振荡时钟电路,外接晶振以及电容C1和C2构成了并联谐振电路接在放大器的反馈回路中,对接电容的值虽然没有严格的要求,但电容的大小会影响振荡频率的高低,振荡器的稳定性,起振的快速性和温度的稳定性。晶振的频率可在1.2MHZ~12MHZ之间任选,电容C1和C2的典型值在20pf~100pf之间选择,由于本系统用到定时器,为了方便计算,采用了12MHZ的晶振,采用电容选择30pf。
图3-4 晶振电路的设计
3.1.5 键盘及读数原理
抢答器输入信号由八个小按键控制与单片机的P1口连接,当有按键按下的时候,就产生了有效地输入信号。根据P1口按键输入的高低电平,判断是哪个按键按下,并执行相应的操作。
键盘是人与微机打交道的主要设备,按键的读取容易引起误动作。可采用软件去抖动的方法处理,软件的触点在闭合和断开的时候会产生抖动,这时触点的逻辑电平是不稳定的,如不采取妥善处理的话,将引起按键命令错误或重复执行,在这里采用软件延时的方法来避开抖动。
图3-5键盘电路设计
3.1.6 显示模块电路设计
该模块由共阳LED数码管组成,利用数码管的动态扫描原理,由三极管进行锁存,当控制数码管的IO口P20和P21为低电平时(及三极管基极为低电平),则三极管导通,VCC通三极管给数码管供电,则数码管被点亮,利用数码管点亮的余辉和人眼的视觉暂留原理,则看起来数码管是同时被点亮的。
图3-6 显示电路的设计
3.1.7蜂鸣器报警电路设计
采用三极管的锁存原理,当P31为低电平时,三极管导通,蜂鸣器响。
图3.7 蜂鸣器
图3.8 硬件电路原理图
4抢答器的软件设计
通过AT89S52芯片的控制,从而构成了整个电路。抢答组数可以在六组以内任意使用,其流程如图4-1
开始
倒计时30秒
减小键按下
倒计时减1
增大键按下
倒计时加1
倒计时开始
倒计时为0
蜂鸣器报警,倒计时显示0
显示选手号码,按键锁定
选手按键按下
图4-1抢答系统流程图
4.1 数码显示软件设计
采用动态显示,显示器由2位共阳极数码管组成,数码显示程序流程如图4-2。
图4-2数码显示流程图
4.2 定时器中断软件设计
AT89S52单片机内部有3个定时器T0,T1和T2,本次设计中使用T0工作在方式1,即16位定时器,定时50ms,20次中断产生秒信号,从而控制红绿灯的点亮时间。
工作方式寄存器TMOD用来设置T0、T1的工作方式。这次实习中设置TMOD=0x01,即T0工作于方式0(16位定时器)。
内部定时器/计数器用作定时器时,是对机器周期计数,每个机器周期的长度是12个振荡周期。定时常数的设置可用一下方式计算:
机器周期=12/12MHz=1us
(65536-定时常数)*1.0us=50ms
所以定时常数是50000。
图 4-3抢答器定时器中断流程图
5电路的调试
5.1电路模块调试
本设计硬件部分主要为显示模块按键模块。硬件电路功能检测主要针对这两部分进行测试。
对于显示电路,由于使用的是二联数码管显示屏,首先要确定数码管的共阴还是共阳极。因此先用万用表检测是什么极性。然后再先固定下,检查显示电路能否正常显示。最后再焊接上去。
对于按键部分,首先要确定各个按键是否完好,先自己接到一个简易的电路上测试下,确定完好后再焊接。
5.2 软件调试的基本方法
软件的设计与调试实行分模块实现方法。本设计软件调试中的分模块包括显示功能模块、抢答功能模块以报警功能模块。各个独立模块功能调试成功后,将这些模块程序通过主程序合并在一起,最后再对合并后的总程序进行调试。,再烧写进单片机看能否在实际电路板上正常工作。编程语言的软件设计采用C语言编写.
5.3 软件调试问题分析
LED显示问题:本次设计的最终方案是采用LED显示屏实现显示功能,最初数码管显示不正常,出现闪烁现象。通过调试发现这是由于延时时间选择不当会使人眼产生视觉暂留效果,每一次显示时都必须加入适当的时间延时。由于一开始所选用的延时时间太短,因此出现闪烁现象,在增加显示延时之后,数码管显示正常。
按键消抖问题:在最初编写程序时,键盘控制部分按照常例加入了按键消抖程序。在实际调试中,发现按键出现反应不灵敏现象。这是因为在键盘控制程序中,除了消抖程序外,还加入了按键提示音程序(每次按压键盘时,蜂鸣器发出“哔”的一声提示音)。由于在调用提示音子程序时,实际上已实现了一次时间的延时,因此再加入按键消抖程序的延时后,致使延时时间过长而出现按键反应不灵敏问题。通过调试发现提示音子程序本身所产生的延时已能够满足按键消抖时间延迟的要求,因此在键盘控制程序中无需再加入专门的按键消抖程序。在去除按键消抖程序后,按键控制灵敏度恢复正常。
致 谢
经过近一个月的努力,在老师及同学的指点下,我成功的完成了设计任务,更重要的是让我重新认识到了自学的重要性,以及学以致用的道理。我在图书馆查阅了大量的资料,并通过上网解决了很多棘手的问题。让我真真正正的掌握了设计一个课题的方法,步骤,和提高了解决问题的能力。
我觉得本次设计的重点和难点都是程序的编写及调试,在编写过程中遇到了很多的问题,比如时间的显示,按键的延时去抖动等问题,这些问题都通过查找资料成功的解决了。
参考文献
[1]吴金戌.8051单片机实践与应用[M].北京:清华大学出版社,2003,9.60~78
[2]巧 媛.单片机原理及应用(第二版)[M].北京:电子工业出版社,2003,2.101~208
[3]王松武.电子创新设计与实践[M].北京:国防工业出版社,2005,2.12~16
[4]彭 为.单片机典型系统设计实例精讲[M].北京:电子工业出版社,2006,5.33~57
[5]余发山.单片机原理及应用技术[M].中国矿业大学出版社,2003,8.88~121
[6]余锡存.单片机原理及接口技术[M].陕西:西安电子科技大学出版社,2000,7.99~134
附件1:源程序代码
/***********************************************************
抢答器程序
***********************************************************/
#include <reg52.h>
#define uchar unsigned char //宏定义
#define uint unsigned int
uint disnum,num,i;
uchar count,temp;
sbit bell=P3^1; //蜂鸣器控制端口s
//sbit key=P3^0;
sbit wela1=P2^1;
sbit wela2=P2^0;
sbit s1=P3^5;
sbit s2=P3^6;
sbit s3=P3^7;
uchar code table[]=
{
0x81,0xE7,0x92,0xC2,0xE4,0xC8,0x88,0xE3,0x80,0xC0
};
uchar code table1[]=
{
0x88,0xEE,0x94,0xC4,0xE2,0xC1,0x81,0xEC,0x80,0xC0
};
/******************************************/
/* 延时子程序 */
/******************************************/
void delay(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=200;b>0;b--);
}
/******************************************/
/* 显示子程序 */
/******************************************/
void display(disnum)
{
uchar shi,ge;
shi=disnum/10;
ge=disnum%10;
P0=table[shi]; //送入段选信号
wela2=1;
wela1=0;
delay(5);
P0=table1[ge];
wela2=0;
wela1=1;
delay(5);
}
/******************************************/
/* 初始化程序 */
/******************************************/
void keyscan()
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
disnum+=1;
if(disnum==99)
disnum=30;
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
disnum-=1;
if(disnum==0)
disnum=30;
}
}
}
void init()
{
P1=0xff; //P1口清1
temp=P1;
disnum=30; //30秒到计时
EA=1;
TMOD=0x10;
ET1=1;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
}
/******************************************/
/* 主程序 */
/******************************************/
void main()
{
init(); //调用初始化程序
while(1)
{
keyscan();
display(disnum);
if(s1==0)
{
delay(5);
if(s1==0)
{
TR1=1;
while(1)
{
temp=P1;
if(temp==0xff)
{
display(disnum);
temp=P1; //判断之前,先把P1口的数据送给temp;
// while(temp!=0xff);// 如果 再有按键按下去,程序不起作用
}
//独立键盘扫描程序
if(temp!=0xff)//有键按下
{
delay(5);//软件延时消抖
temp=P1;
while(temp!=0xff)//再次确认有键按下
{
TR1=0;
temp=P1;
switch(temp)//判断哪个键按下
{
case 0xfe : disnum=1;
break;
case 0xfd : disnum=2;
break;
case 0xfb : disnum=3;
break;
case 0xf7 : disnum=4;
break;
case 0xef : disnum=5;
break;
case 0xdf : disnum=6;
break;
case 0xbf : disnum=7;
break;
case 0x7f : disnum=8;
break;
}
P0=table1[disnum];//显示所按下的键
wela2=0;
wela1=1;
bell=0; //开蜂鸣器
delay(500);
bell=1;
while(1);//进入死循环,将所按下的键显示并定格,防止有键再按下时将其覆盖;
}
}
}
}
}
}
}
void time() interrupt 3
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
count++;
if(count==20)
{
count=0;
disnum--;//30秒倒计时
if(disnum<=5&&disnum>0)
{bell=0;
delay(1000);
bell=1; //关闭蜂鸣器
}
if(disnum==0)
{
TR1=0;//关断定时器0
bell=0; //开蜂鸣器
for(i=0;i<600;i++)//循环调用显示0延时,
display(disnum);
bell=1; //关断蜂鸣器
while(1); //程序停止到这里
}
}
}
展开阅读全文