基于51单片机开发的十路抢答器设计:详细教程

一、设计要求

(1)抢答器同时供10名选手或10个代表队比赛。

(2)设置一个系统清除和抢答控制开关S,该开关由主持人控制。

(3)抢答器具有锁存与显示功能。即选手按动按钮,锁存相应的编号,并在LED数码管上显示,同时扬声器发出声响提示。选手抢答实行优先锁存,优先抢答选手的编号一直保持到主持人将系统清除为止。

(4)抢答器具有定时抢答功能,抢答的时间由主持人设定(如30秒)。当主持人启动"开始"键后,定时器进行减计时,同时扬声器发出短暂的声响,声响持续的时间0.5秒左右。

(5)参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号和抢答的时间,并保持到主持人将系统清除为止。

(6)如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,定时显示器上显示00

二、设计准备

Keil uVision编写代码,Proteus 8 Professional仿真和调试,立创EDA进行绘制PCB板封装。

已经绘制的程序流程图:

faf0fc9ff85141e8bc573f637815dd48.png

三、绘制仿真图

首先选择满足设计要求的元器件,建立合适的电路图。如果先编写代码的话,还不确定一些引脚、开关、晶振电路、器件参数等等的设计,直接写代码不实际。笔者用到的器件有共阳极四位数码管7SEG-MPX4-CA,单片机AT89C52,按钮开关BUTTON,有源蜂鸣器BUZZER,电容CAP,晶振CRYSTAL,NPN三极管,RES电阻,SW-SPST单刀单掷开关。按照如图所示,在元器库里搜索所需元器件,其余的电源和地线在左侧终端模型中直接选择。

补充知识:

1、数码管原理:

66e9315f6b0e400ba4c24550cdc421b0.png6cc81b6e61414a2ebabc9ec14ac36b2d.png

 单个数码管的内部电路图:a~h每个数字代表一个发光二极管,v是公共端,可以接地或者电源,对应共阴极和共阳极接法。a~g段数码管用来显示数字,h显示小数点。为了便于封装,数码管的外部一共10个引脚,5和10连在一起接公共端,其余各对应一个发光二极管。a~f六个数码管亮能实现显示数字0;b、c两个数码管点亮,实现数字1的显示。Proteus中的数码管有八个引脚,输入八位的二进制数就能实现数字的显示。

06f5cbb08a5a47208dc6fa698df84e19.png

四位数码管的段选端口是连接在一起的。1、2、3、4是位选信号。如果我们将段选信号输入到端口,那么所有的数码管显示的数字相同。为了显示不同数字,每次只让一个位选信号使用,其他三个就禁止,虽然每个时刻只有一个数码管显示,但是下一时刻就切换要显示的数字。因为肉眼捕捉的速度比较慢,信号切换的速度很快,这样就是看到四个数码管同时亮动。

共阴极和共阳极数码管

共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,反之,相应字段就不亮。

共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,反之,相应字段就不亮。

数码管公共极的连接不同,共阳数码管在应用时应将公共极COM接到+5V,共阴数码管在应用时应将公共极COM接到地线GND上

2.有源蜂鸣器和无源蜂鸣器

f190f19d34ec453aae117bd2b7370d5a.png

在Proteus中有源蜂鸣器是下面这个。有源蜂鸣器使用简单,不能设置频率,只能发出单音,无源可以设置频率。两者对输入信号的要求不一样:有源蜂鸣器工作的理想信号是直流电,通常标示为VDC、VDD等。蜂鸣器内部有一简单的振荡电路,能将恒定的直流电转化成一定频率的脉冲信号,从面实出磁场交变,带动钼片振动发音。两者所接电路不一样。选择有源蜂鸣器时,选择其电压为5V。

 9ddb47a60ed6415d94768a958a1b5562.png

Proteus电路图

总线设置时,按下英文模式键盘的快捷键a,弹出窗口,写入NET=P0#,可以依次给导线注释P1、P2……,写入NET=k,可以给导线直接标注为k。

 四、编写keil代码生成hex文件

 五、进行Proteus仿真

 双击单片机把hex程序文件添加进去,然后进行运行仿真。笔者做的只是简单的十路抢答器,在运用单片机串口的时候,整个P0口做数码管的段选码,整个P2做位选码,两个串口都来实现这些功能了,在数码管显示的过程中P2口的状态一直在改变,这样就很难再加其他功能。所以再加入控制开关的时候另辟蹊径,选择带电源的单刀单掷开关,加入进去后也没有影响数码管的显示。报警器的代码设置因为使用了很多其他方法,诸如改变报警的条件,启动开关开启和秒数减到0才报警;或者让位选码的设定这和单独的四个iO口有关;或者把报警电路接到P3口,再改变9,10号的代码显示;或者用stcisp软件设置单片机的P4口做io口使用等等……控制效果都不如现在的这个电路。最后设置为当倒计时为29秒开始响,到28他自然就不响了,以及倒计时为00时报警,但此时做不到报警响铃具体时间自动停下,只能关闭启动开关再按下复位开关,报警解除。其他附加功能难以实现,这是笔者的本次设计的最大不足。咸鱼一条的我肝了许多也解决不了问题,如果使用寄存器来节省io口的话可能就更好,但实在能力有限,添加锁存器时写入代码更加运行不了,对电路内部原理和C语言只是略微了解。有兴趣的小伙伴可以去了解一下,锁存器在数码管和单片机的使用。不过好在,整个设计满足基本的设计要求。

六、立创创建原理图和封装

 Proteus文件无法直接转化为立创图。根据Proteus的原理图用立创绘图。在元件库中找不到元件时,小伙伴们可以先把Proteus上的名称百度搜索他的中文名或另外的英文名,再在元件库中搜索对应的中文或英文名。单片机上没用到的io口不需要接线了,在后续绘制pcb板铺铜会处理那些多余的引脚。注意,根据立创使用守则说明书,使用总线的原理图不能直接转换为pcb板。我已经吃过这个亏了。

立创有时候连接导线会突然停下来,让人误以为连上了,放大检查所有线路都连接完整后,转化为pcb。

 

 为了节约材料,选择合适的板子大小,把元件放入板子上,并且按实际情况放置好开关等元件。

下载好本地自动布线程序,开始自动布线。布线后根据实际线路需要再设置其他属性,比如连接电源的导线应该加粗。选择底层视图,去掉元件显示,找到一根电源线,右键查找相似对象,然后再后边的属性栏增加导线宽度。

 最后为了减小回路面积,降低地线阻抗,使电镀层压不变形,给pcb板铺铜。点击铺铜工具,分别在顶层和底层给板子内部四角依次点击 ,最后铺铜完成。详细的铺铜要求可以参考其他文献,笔者只做了简单地线铺铜  。


感谢所有读者能看到这里~o(* ̄▽ ̄*)ブ

看到周围很多同学因为课设而头疼,自己做出来一个课设也希望能给其他人帮助。第一次写类似的文章,我是自动化专业的,还做了很多课设希望以后再发出来。最后keil软件编写的代码也全部奉献啦,创作不易,期待帅哥美女们一键三连(☆▽☆)也欢迎各位留言交流。

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
/****************共阳极数码管9-0***************/
char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar code weima[]={0x80,0x40,0x20,0x10,0x08,0x04,0x01};
uchar disp[]={0xc0,0xb0,0xbf,0xbf};
sbit k=P2^0;
sbit Buzzer=P2^2;
uchar miao=30;//设定倒计时
uchar i=1,count=0,scan=0,shu,shu1;
void keys(void);	
void delay(uint t)
{while(t--);}
void xianshi(void)
{
     if(++scan==5)scan=1;
	 P2=weima[scan-1];
	 P0=disp[scan-1];
	 delay(200);
}
main()   
	{  TMOD=0x01;//t0,方式1
	   TH0=0x3c;TL0=0x0b0;
	   EA=1;
	   ET0=1;
	   P1=0xff;
       P3=0xff;
	   TR0=1;
	   while(1)
	 {
		  	 	   if(disp[0]==table[9]&&disp[1]==table[2]) 
		{ 
		  Buzzer=1;
		  
		}
	      if(miao==0)
		  {TR0=0;  
		  Buzzer=1;
		  delay(2000);
		  Buzzer=0;
		}
		  xianshi();
		  
		    if(miao!=0)
			if(P1!=0xff||P3!=0xff)
		{	     
		  delay(5);
              if(P1!=0xff||P3!=0xff)
             {
              switch(P1)
              {  
              case 0xfe : shu=1; shu1=0;
                  break;
              case 0xfd : shu=2; shu1=0;
                  break;
              case 0xfb : shu=3; shu1=0;
                  break;
              case 0xf7 : shu=4; shu1=0;
                  break;
              case 0xef : shu=5; shu1=0;
                  break;
              case 0xdf : shu=6; shu1=0;
                  break;
              case 0xbf : shu=7; shu1=0;
                  break;
              case 0x7f : shu=8; shu1=0;
                  break;
              }
              switch(P3)
             {
case 0xbf : shu=9; shu1=0;
break;
case 0x7f : shu=0; shu1=1;
break;}
}

	  disp[2]=table[shu];
	  disp[3]=table[shu1];
      TR0=0;               //定时器停止倒计时
	while(1){xianshi();}   //保证第一个按键有效
	   }
	 } 	 
}			  	

void Timer0Interrupt(void) interrupt 1
{
	 if(k==1)
{delay(10);
if(k==1)
{
if(++count==20&&k==1)
	 {count=0;
	 miao--;
	 disp[0]=table[miao%10];
	 disp[1]=table[miao/10];
	 }
	 }
}
}

物联沃分享整理
物联沃-IOTWORD物联网 » 基于51单片机开发的十路抢答器设计:详细教程

发表评论