自动化—单片机—有线抢答器的设计

Posted 李聪卓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动化—单片机—有线抢答器的设计相关的知识,希望对你有一定的参考价值。

功能需求概述

源代码:

#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code seg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};     //共阳极数码管编码表0-9显示
sbit key1 = P1^0;
sbit key2 = P1^1;
sbit key3 = P1^2;
sbit key4 = P1^3;
sbit begin = P2^1;
sbit clear = P2^2;
sbit addtime = P3^2;            //按键定义
sbit P2_4 = P2^4;
sbit P2_5 = P2^5;
sbit P2_6 = P2^6;
sbit P2_7 = P2^7;              //数码管显示控制
sbit sounder = P3^7;          //喇叭控制
bit key1_flag = 0;
bit key2_flag = 0;
bit key3_flag = 0;
bit key4_flag = 0; 
bit begin_flag = 0;
bit clear_flag = 0;           //按键标志位
bit a = 0;
uchar second = 0;
uchar b=0;
uchar c=0;
uchar i=0;
uchar j=1;
uchar k=0;
uchar number=0;
uchar number_display=0;

void delay(uint m)
{
    uchar n;
    while(m--)
    {    
        for(n=0;n<120;n++);
    }
}
void display(uchar number,uchar second)    // 数码管显示驱动函数
{
    uchar second_first,second_second;
    second_first=second/10;
    second_second=second%10;           //将秒数分成两位
    P2_7=0;
    P2_4=1;          //选通第一个数码管
    P0=0xc0 ;   //显示0
    delay(2);                            
  P2_4=0;
    P2_5=1;         //选通第二个
    P0 = seg[number];           //显示编码数字
    delay(2);
    P2_5=0;
    P2_6=1;                       //选通第三个
    P0=seg[second_first];               //显示一位秒数
    delay(2);
    P2_6=0;
    P2_7=1;                                    //选通第四个
    P0=seg[second_second];                    //显示另一位秒数
    delay(2);    
}

void display2()               //显示00功能
{
    P2_7=0;   
  P2_6=1;              //选通一位秒表数码管
    P0 =seg[0];                     //显示0
    delay(2);
    P2_6=0;
    P2_7=1;            //选通另一位秒表数码管
    P0=seg[0];                    //显示0
    delay(2);    
}

uchar key_scan4()     //四位抢答键扫描函数
{
    if(key1==0)     //如果按键1按下
    {
        delay(10);                    //防抖动延时
        if((key1==0)&&(!key1_flag))            //如果仍旧按下
        {
            key1_flag=1;
            number=1;                                //数字变量赋值1
            number_display=number;
        }
    }
    else
    {
        key1_flag = 0;
        number = 0;    
    }
    if(key2==0)        
    {
        delay(10);
        if((key2==0)&&(!key2_flag))
        {
            key2_flag=1;
            number=2;
            number_display=number;
        }
    }
    else
    {
        key2_flag=0;
        number=0;    
    }
    if(key3==0)    
    {
        delay(10);
        if((key3==0)&&(!key3_flag))
        {
            key3_flag=1;
            number=3;
            number_display=number;
        }
    }
    else
    {
        key3_flag=0;
        number=0;    
    }
    if(key4==0)    
    {
        delay(10);
        if((key4==0)&&(!key4_flag))
        {
            key4_flag=1;
            number=4;
            number_display=number;
        }
    }
    else
    {
        key4_flag=0;
        number=0;    
    }                                     
    if(number_display!= 0)    
    {
        return 1;
    }
    else
    {
        return 0;                        //返回值控制是否有键按下
    }    
}

void begin_keyscan()    //开始键扫描函数
{
    if(begin==0)            //启动按下
    {    
        delay(10);                //防抖动延时
        if((begin==0)&&(!begin_flag))    //如果还是按下,同时标志位为0
        {
            begin_flag=1;     //标志位置1
            sounder=0;          //喇叭响
            j=1;
            b=0;                   //辅助循环变量
            a=1;
      if(second!=0)                //秒数不为0
          {
               TR0=1;                       //打开定时器0
          }
      }
    }
    else
    {
        begin_flag=0;    
    }    
}
void reset_keyscan()    //复位键扫描函数  
{
  if(clear==0)
    {
        delay(10);           //防抖动
        if((clear == 0)&&(!clear_flag))//如果仍旧按下
        {
            clear_flag=1;
            number_display=0;
            sounder=1;                                //关闭喇叭
            j=0;
            b=1;                                           //循环控制变量赋值,可跳出主程序的某个死循环
        }
    }
    else
    {
        clear_flag=0;
    }    
}

void main()
{
    TMOD=0x01;
    TH0=0x3c;
    TL0=0xb0;               //定时0.05s
    EA=1;
    EX0=1;
    ET0=1;
    IT0=1;
    TR0=0;
    while(1)
    {     
        begin_keyscan();          //判断是否按了开始
        reset_keyscan();            //判断是否复位
        second=c;                    //每次将按键加的秒数实时显示
        while(a)                //当开始按下
        {
            while(!key_scan4())     //当无人抢答
            {         
                display(number_display,second);          //显示号码和秒数,一秒后时间减一显示
                while((second==0)&&(j==1))                //减到0同时j=1
                {
                  display2();                           //显示00
                    sounder=0;                 //报警
                    reset_keyscan();                   //按下复位j=0,跳出循环
                }
                if(second==0)                           //如果秒数减到0,跳出抢答循环
                { 
                  break;
                }
            }                                  
            TR0=0;                      //关闭定时器
            k=0;                      //复位0
            while(b==0)                               
            {
                 display(number_display,second);  //显示当前数据
                 reset_keyscan();
            }
            a=0;
            break;
        }
        display(number_display,second);   
    }                
}

void timer0() interrupt 1
{
    TH0=0x3c;
    TL0=0xb0;
    k++;
    if(k==10)       //0.5s控制关闭喇叭
    {
      sounder=1;
    } 
    if(k==20)          //1s控制秒数倒计时
    {
        k=0;
        second--;
        if(second==0)
        {
            TR0=0;
            number_display=0;
            a=0;
        }
    }
}

void int0() interrupt 0     //外部中断,当加时按钮按下一次加时间1S
{
  if(addtime==0)
  {
    if(i<=29)            //变量控制增加秒数直到30
      {
      i++;
        c=c+1;
      }
      else 
    {
          i=0;
          c=0;
        }
   }
}
 
                                  

代码写的逻辑很清楚,注释和很明确。推荐自动化的同学细细研读。

最后小剧场:

事情起因:卢思毅同学邀请本人代画此程序设计流程图,当时是一口答应了;后来才发现画这个程序流程图是有多难。后来到了交图时间,只能草草收场,十分尴尬;没能给学霸菇凉画出来,还耽误人时间,十分抱歉。

源代码版权声明归卢思毅所有,在此有本人只进行总结和归纳,弥补自己对单片机领域的不足。

研究汇编语言,最好看是多看看单片机这块儿。

以上是关于自动化—单片机—有线抢答器的设计的主要内容,如果未能解决你的问题,请参考以下文章

51单片机的4位抢答器proteus仿真设计(仿真+源码+参考报告)

基于单片机8位竞赛抢答器仿真设计-全套资料

基于单片机16位智能抢答器设计(裁判功能LCD数码管显示)汇编

基于单片机节日彩灯控制器系统设计基于单片机脉搏检测和体温检测设计基于单片机可燃气体检测及报警系统基于单片机可调八路抢答器仿真设计-全套设计资料

微处理器原理与接口课程设计-八路抢答器

51单片机 八路抢答器+Proteus仿真