原理图整体
本设计利用51单片机中断函数来查询抢答位置,除了一般抢答器用到的基本元件外,还用到了74LS30(八路与非门)与74LS04(非门)。下面对原理图进行分块介绍
抢答按钮部分(注意非门接到AT89C52的P3.3 INT1触发)
led灯连接部分 (采用灌电流的形式,注意P0口上拉电阻与led线路上的保护电阻)
实际电路中,通常外界供电5V,led灯的压降为2V,工作电流为1-5mA,安全电阻通常在1-3KΩ
数码管连接部分
采用74HC573连接数码管,增加端口的驱动能力,也节约了端口
P3端口与蜂鸣器
蜂鸣器要保证供电,采用三极管增加驱动能力
程序流程图
C程序
#include <reg52.h> //添加两类头文件
#include <intrins.h>
#define uchar unsigned char //对两种关键字进行简化替换
#define uint unsigned int
#define led P0 //对端口名字进行替换
#define shuma P2 //有利于在替换不同封装时调整代码
#define button P1
bit flag1,flag2,flag3,flag4,liushui,setflag; //变量的定义
sbit DUAN=P3^0;
sbit WEI=P3^1;
sbit BUZZ=P3^5;
sbit start=P3^4;
sbit set=P3^6;
sbit reset=P3^2;
uchar temp;
uchar count=1;
uchar timecount;
uchar numshow;
uchar numget;
uchar t;
uchar pro;
uchar changet=20;
uchar showt;
uchar code showcode[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴极0-9的段码
uchar code NO[2]={0x37,0x3f}; //显示字母NO的段码
uchar code HELLO[5]={0x76,0x79,0x38,0x38,0x3f};//显示HELLO的段码
void delay(uchar i); //函数的定义
void shumashowcountdown(uchar num);
void shumashowget(uchar a);
void xiaochu();
void sound();
void showhello();
void showno();
void main()
{
sound(); //开机叫一声
EA=1; //进行中断设置
EX0=1;
EX1=0;
IT0=1;
IT1=1;
PX0=1;
PX1=1;
while(1)
{
if(count==1)
{flag1=1;}
while(flag1) //状态1 数码管显示HELLO等待进行复位
{
showhello();
}
xiaochu();
sound();
while(flag2) //状态2 等待计时开始或者修改计时时间
{
led=0x00;
xiaochu();
if(start==0) //等待计时
{
EX0=1;
flag2=0;
flag3=1;
flag4=0;
EX1=1;
ET0=1;
TH0=0xd8;
TL0=0xf0; // 每次定时器中断时间是10ms
TR0=1;
timecount=0;
numshow=changet;
shumashowcountdown(numshow);
led=0xfe;
liushui=0;
}
if(flag3==0)
{
delay(200);
}
if(set==0) //修改计时时间
{
set=1;
start=1;
reset=1;
setflag=1;
EX0=0;
EX1=0;
led=0xaa;
delay(200);
while(setflag==1)
{
shumashowcountdown(changet);
if(set==0)
{
delay(10);
if(set==0)
{
setflag=0;
EX0=1;
EX1=1;
set=1;
}
}
if(start==0)
{
changet=changet-1;
led=_crol_(led,1);
delay(200);
}
if(reset==0)
{
changet=changet+1;
led=_cror_(led,1);
delay(200);
}
}
}
}
sound();
while(flag3) //状态3 开始进行倒计时
{
if(numshow!=0)
{
shumashowcountdown(numshow);
}
if(liushui==1)
{
led=_crol_(led,1);
liushui=0;
}
if(numshow==0) //如果在规定时间内无人进行抢答
{ //数码管显示NO
ET0=0;
EX1=0;
showno();
}
}
sound();
while(flag4) //状态4 显示抢答结果
{
led=temp;
shumashowget(numget);
}
}
}
void delay(uchar i) //延时时间
{
uchar j=250;
uchar c=5;
while(i--)
{
while(j--);
}
}
void sound() //蜂鸣器发出声音
{
BUZZ=0;
delay(200);
BUZZ=1;
}
void xiaochu() //对数码管进行消隐
{
WEI=1;
shuma=0xff;
WEI=0;
shuma=0x00;
DUAN=1;
shuma=0x00;
DUAN=0;
}
void shumashowget(uchar a) //数码管显示抢答结果
{
WEI=1;
shuma=0x7f;
WEI=0;
DUAN=1;
shuma=showcode[a];
DUAN=0;
delay(100);
}
void shumashowcountdown(uchar num) //数码管显示倒计时
{
uchar a[2];
a[1]=num%10;
a[0]=num/10;
WEI=1;
shuma=0x7f;
WEI=0;
shuma=0x00;
DUAN=1;
shuma=showcode[a[1]];
DUAN=0;
shuma=0xff;
delay(2);
WEI=1;
shuma=0xbf;
WEI=0;
shuma=0x00;
DUAN=1;
shuma=showcode[a[0]];
DUAN=0;
shuma=0xff;
delay(2);
}
void int1rst() interrupt 0 //INT0的中断函数 用于reset恢复初始状态
{
if(count==1)
{flag1=0;
count=0;
}
flag2=1;
flag3=0;
flag4=0;
xiaochu();
IE1=0;
}
void timer() interrupt 1 //定时器T0中断函数 用于精确计秒
{
timecount++;
if(timecount==100)
{
numshow--;
liushui=1;
timecount=0;
}
}
void int1grad() interrupt 2 //INT1的中断函数,用来检测哪个端口被按下
{
temp=button;
delay(2);
if(temp==button)
{
if(temp==0xfe)
{
numget=1;
}
if(temp==0xfd)
{
numget=2;
}
if(temp==0xfb)
{
numget=3;
}
if(temp==0xf7)
{
numget=4;
}
if(temp==0xef)
{
numget=5;
}
if(temp==0xdf)
{
numget=6;
}
if(temp==0xbf)
{
numget=7;
}
if(temp==0x7f)
{
numget=8;
}
flag2=0;
flag3=0;
flag4=1;
TR0=0;
ET0=0;
EX1=0;
}
}
void showhello() //数码管显示HELLO
{
pro=0xf7;
for(t=0;t<5;t++)
{
WEI=1;
shuma=pro;
WEI=0;
shuma=0x00;
DUAN=1;
shuma=HELLO[t];
DUAN=0;
shuma=0xff;
delay(2);
pro=_crol_(pro,1);
}
}
void showno() //数码管显示NO
{
if(showt==0)
{
sound();
showt=1;
}
pro=0xbf;
for(t=0;t<2;t++)
{
WEI=1;
shuma=pro;
WEI=0;
shuma=0x00;
DUAN=1;
shuma=NO[t];
DUAN=0;
shuma=0xff;
delay(2);
pro=_crol_(pro,1);
}
led=0x00;
}
仿真效果
状态一 欢迎界面
状态二 修改计时时间与等待开始
状态三 抢答倒计时与无人应答报警
状态四 显示抢答结果
操作说明
上电后显示HELLO
按reset键进行等待
之后按START键进行倒计时开启抢答
状态二 在按led灯全亮的状态下,可以修改倒计时时间
按下set键后,led灯半亮
reset键增加时间
start键减少时间
修改后再次按下set键回到led灯全亮状态等待计时开始
无人应答或者抢答结束后按reset键可以回到状态二 等待下一次抢答开始