摘 要:本文介绍用单片机技术设计的电子抢答器,除能完成基本的抢答功能外,还可进行加分、减分、存贮显示各组分数、答题限时抢答限时等功能.主要有选手抢答部分、主持人控制部分和数码管显示部分。优点是利用单片机来设计抢答器,使以上问题得以解决,即使两组的抢答时间相差几微秒,也可分辨出哪组优先答题。硬件电路简单,功能齐全,操作方便,是一款即先进又实用的电子抢答器.
关键词:单片机、抢答、显示、控制
一、使用说明:首先由主持按下开始键,单片机开始倒计时,选手们才可以开始抢答,单片机从30秒开始倒计时,如果在30秒内无人抢答,则自动放弃,进入下一题,若有人抢答,则单片机会自动检测是几号首先抢答,做出判断,之后数码管会显示,然后单片机重新倒计时,从90秒开始,若在90秒内回答完并回答正确,主持人可以按加分键,则所的分数会显示在选手的数码管上,若回答错误,则主持人可以通过减分键进行减分,然后进入下一题。
二、方案论证:
方案一:利用集成芯片设计,优点是造价低,但缺点很多,功能单一,操作不便。
方案二:利用单片机设计,充分利用单片机的资源:定时器和IO口,利用定时器实现倒计时功能,抢答部分采用独立式键盘,显示部分采用数码管扫描实现,其外围部分简单,主要是由单片机控制,把程序编写成攻即可。
综合考虑以上两个方案,决定采用第二个方案,利用单片机实现。
三、方案设计
四、程序
本作品的核心部分是单片的控制部分,所以便一个合适的程序是极其重要的,程序如下:
#include<reg52.h>
Static unsigned char dm[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
static unsigned char px2[11]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff,0xff,0xff};
static unsigned char px3[11]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xbf,0x7f};
static unsigned char xs[11]={0xc0,0xa4,0xc0,0xa4,0xc0,0xa4,0xc0,0xa4,0xc0,0xb0,0xc0};
static unsigned char dj[4]={0};
static unsigned char n,r;
static unsigned char t=30; //t:时间,k:溢出
static unsigned char k,k2=0;
static unsigned char kk,p;
static unsigned char fen1=20,fen2=20,fen3=20,fen4=20;
///
void djxs1(unsigned char t) //倒计时函数1
{
unsigned char i;
if(t>23) dj[3]=~((~dj[3])>>1);
if((t>16)&&(t<24)) dj[2]=~((~dj[2])>>1);
if((t>8)&&(t<17)) dj[1]=~((~dj[1])>>1);
if((t>0)&&(t<9)) dj[0]=~((~dj[0])>>1);
for(i=0;i<4;i++)
{
SBUF=dj[i];
while(!TI){}
TI=0;
}
}
/
void djxs2(unsigned char t) //倒计时函数2
{
unsigned char i;
if(t>69) dj[3]=~((~dj[3])>>1);
if((t>48)&&(t<70)) dj[2]=~((~dj[2])>>1);
if((t>24)&&(t<49)) dj[1]=~((~dj[1])>>1);
if((t>0)&&(t<25)) dj[0]=~((~dj[0])>>1);
for(i=0;i<4;i++)
{
SBUF=dj[i];
while(!TI){}
TI=0;
}
}
//
void t1(void)interrupt 3 //定时器1中断
{
TH1=0X15;
TL1=0XA0;
k++;
if(k>20)
{
k=0;
k2++;
// if(t==90)
// for(r=0;r<4;r++)dj[r]=0;
if(kk)djxs1(t);
if(p&&(k2==3)){k2=0;djxs2(t);} //3秒
//1秒 //灯倒计时
t--;
xs[9]=dm[t/10];
xs[10]=dm[t%10];
if(t==0){for(r=0;r<4;r++)
dj[r]=0;
TR1=0;
xs[9]=dm[3];
xs[8]=dm[0];}
}
}
void t0(void)interrupt 1 //定时器2中断
{
P0=xs[n];
P2=px2[n];
P3=px3[n];
n++;
if(n>10)n=0;
TH0=0Xfe;
TL0=0X00;
}
char jianpan() //键盘函数
{
unsigned char x,d=500;
P1=0xff;
while(P1==0xff);
x=P1;
while(d--);
d=500;
while(P1!=0xff);
return x;
}
main()
{unsigned char x,y,m;
// unsigned char k;
IE=0X8a;
//TMOD=0X01;
TMOD=0X11;
TH0=0Xfe;
TL0=0Xb8;
TR0=1; //数码管显示
TH1=0X15;
TL1=0XA0;
loop: TR1=0;
t=30;
xs[8]=dm[0];
xs[9]=dm[3];
xs[10]=dm[0];
for(m=0;m<4;m++)
{dj[m]=0;
}
for(m=0;m<4;m++)
{
SBUF=dj[m];
while(!TI){}
TI=0;
} //灯全亮
while(1)
{
x=jianpan(); //扫描键盘
switch(x)
{
case 0xef: //开始键按下
{ kk=1;
p=0;
t=30; //音乐
TR1=1; //灯逐个灭,数码管减一
while(t) //30秒内
{ y=jianpan();
//if(y&&0x0f!=0x0f)
for(m=0;m<4;m++)
{
dj[m]=0;}
k2=0;
t=90;
p=1;
switch(y)
{
case 0xfe:{xs[8]=dm[1]; //一键按下
kk=0;t=90;k2=0;
while(1)
{ //重新倒计时
if(P1==0xdf){fen1+=5;
xs[0]=dm[fen1%10]; //加分
xs[1]=dm[fen1/10];goto loop;}
if(P1==0xbf){fen1-=5;
xs[0]=dm[fen1%10]; //减分
xs[1]=dm[fen1/10];goto loop;}
}
break;} //显示一
case 0xfd:{xs[8]=dm[2]; //二键按下
kk=0;t=90;k2=0;
while(1)
{
if(P1==0xdf){fen2+=5;
xs[2]=dm[fen2%10];
xs[3]=dm[fen2/10];goto loop;}
if(P1==0xbf){fen2-=5;
xs[2]=dm[fen2%10];
xs[3]=dm[fen2/10];goto loop;}
}
break;} //显示二
case 0xfb:{xs[8]=dm[3]; //三键按下
kk=0;t=90;k2=0;
while(1)
{ //重新倒计时
if(P1==0xdf){fen3+=5;
xs[4]=dm[fen3%10];
xs[5]=dm[fen3/10];goto loop;}
if(P1==0xbf){fen3-=5;
xs[4]=dm[fen3%10];
xs[5]=dm[fen3/10];goto loop;}
}
break;} //显示三
case 0xf7:{xs[8]=dm[4]; //四键按下
kk=0;t=90;k2=0; //重新倒计时
while(1)
{
if(P1==0xdf){fen4+=5;
xs[6]=dm[fen4%10];
xs[7]=dm[fen4/10];goto loop;}
if(P1==0xbf){fen4-=5;
xs[6]=dm[fen4%10];
xs[7]=dm[fen4/10];goto loop;}
}
break;} //显示四
default:break;
}
}
goto loop;} //无人抢答
default:break;} //开始switch
} //总while
}
五、作品调试
作品调试的过程中主要是程序条是比较繁琐,硬件的制作工作量挺大的,主要是因为几个键盘是独立的,数码管是采用扫描显示的,每块小板上都有许多排针,程序主要在两个倒计时之间的转换上有点难调,定时器用了两个,调试往往顾此失彼,后来就实行模块式调试,最终实现了。
六、感想心得
通过这次制作中不断的纠错和调试,我学到了很多包括焊接中要注意的何布板设计的事情,更进一步的了解了单片机的内部资源和应用。理论和实际是存在一定的差距的,只有不断的实践,才能将理论和实践结合起来。
七、参考书目
《单片机应用系统设计技术》 张 齐 编著
《8051单片机实用教程》 徐爱韵 编著
《单片机原理及应用》 孙育才 编著