码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-09-20 12:00:56      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:驱动   技术   推荐   com   版权   break   class   逻辑   外部中断   

功能需求概述

技术分享

源代码:

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

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

最后小剧场:

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

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

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

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

标签:驱动   技术   推荐   com   版权   break   class   逻辑   外部中断   

原文地址:http://www.cnblogs.com/licongzhuo/p/7560354.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!