单片机
返回首页

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

2025-09-22 来源:cnblogs

原理图整体

原理图整体

本设计利用51单片机中断函数来查询抢答位置,除了一般抢答器用到的基本元件外,还用到了74LS30(八路与非门)与74LS04(非门)。下面对原理图进行分块介绍

抢答按钮部分(注意非门接到AT89C52的P3.3 INT1触发)

按键区整体

按键区局部

led灯连接部分 (采用灌电流的形式,注意P0口上拉电阻与led线路上的保护电阻)

实际电路中,通常外界供电5V,led灯的压降为2V,工作电流为1-5mA,安全电阻通常在1-3KΩ

led区

数码管连接部分

采用74HC573连接数码管,增加端口的驱动能力,也节约了端口

数码管区域

P2口

P3端口与蜂鸣器

蜂鸣器要保证供电,采用三极管增加驱动能力

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


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 锂离子/锂聚合物USB电池充电器

  • 18W乙类音频放大器

  • 设计汽车集群电源

  • 6晶体管H桥

  • USB自供电声卡

  • PIC16F84闹钟

    相关电子头条文章