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


    功能需求概述

    源代码:

    #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;
            }
       }
    }
     
                                      

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

    最后小剧场:

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

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

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

  • 相关阅读:
    http协议之状态码
    HTTP协议入门基础
    CI框架使用(一)
    memcache常见现象(一)雪崩现象
    memcached分布式一致性哈希算法
    编译php扩展
    memcached--delete--replace--set--get--incr--decr--stats
    memcached--add使用
    php5.3之命名空间
    MySQL优化(一)
  • 原文地址:https://www.cnblogs.com/licongzhuo/p/7560354.html
Copyright © 2020-2023  润新知