51单片机8位抢答器程序设计与原理图搭建

该设计利用51单片机的中断功能实现抢答器,结合74LS30与74LS04门电路,以及数码管和LED灯显示,具有抢答位置查询和倒计时功能。程序中包含中断服务子程序,用于处理抢答和计时。用户可通过按键修改计时时间,系统在无人应答时会显示NO。
摘要由CSDN通过智能技术生成

原理图整体

本设计利用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键可以回到状态二 等待下一次抢答开始

1)设计内容: 1,利用各种器件设计一个多路智力竞赛抢答器。 2,利用电路板对所设计的电路进行检验。 3,总结检验电路设计结果 2)学习要求: 1,复习编码器、十进制加/减计数器的工作原理,设计可预置时间的定时电路分析与设计时序控制电路。画出定时抢答器的整机逻辑电路图,掌握智力抢答器的工作原理及其设计方法,并对各种元器件的功能和应用有所了解。并能对其在电路中的作用进行分析。例如:555定时器,优先编码器74ls148和rs锁存器74ls279以及十进制同步加/减计数器74ls192。另外对电路图要学会分析。 了解电路设计流程的原理图。每个电路的设计都要有完整的设计流程。这样才能在分析电路是有良好的思路,便于查找出错的原因。 3)设计要求 1. 抢答器同时供8名选手或8个代表队比赛,分别用8个按钮S0 ~ S7表示。 2. 设置一个系统清除和抢答控制开关S,该开关由主持人控制。 3. 抢答器具有锁存与显示功能。即选手按动按钮,锁存相应的编号,并在优先抢答选手的编号一直保持到主持人将系统清除为止。 4. 抢答器具有定时抢答功能,且一次抢答的时间由主持人设定(如30秒)。当主持人启动"开始"键后,定时器进行减计时,同时扬声器发出短暂的声响,声响持续的时间0.5秒左右。 5. 参赛选手在设定的时间内进行抢答,抢答有效,定时器停止工作,显示器上显示选手的编号和抢答的时间,并保持到主持人将系统清除为止。 6. 如果定时时间已到,无人抢答,本次抢答无效,系统报警并禁止抢答,定时显示器上显示00。
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值