找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10459|回复: 2
打印 上一主题 下一主题
收起左侧

求教八路抢答器怎样让按下抢答键后开始60秒倒计时

[复制链接]
跳转到指定楼层
楼主
ID:69248 发表于 2014-11-22 18:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 学习51单片机 于 2014-11-22 18:37 编辑

求教八路抢答器怎样让按下抢答键后开始60秒倒计时
#include <reg51.h>
#include<intrins.h>           //包含_nop_()函数定义的头文件

#include<math.h>

#include<absacc.h>
typedef unsigned char uchar; //无符号字符型
typedef unsigned int uint16; //无符号整型

sbit    KEY1  =  P1^0;      //抢答键1S1

sbit    KEY2  =  P1^1;   //抢答键2S2
sbit    KEY3  =  P1^2;   //抢答键3S3
sbit    KEY4  =  P1^3;   //抢答键4S4
sbit    KEY5  =  P1^4;    //抢答键5S5
sbit    KEY6  =  P1^5;   //抢答键6S6
sbit    KEY7  =  P1^6;   //抢答键7S7
sbit    KEY8  =  P1^7;   //抢答键8S8
sbit    BEEP  =  P3^6;      //蜂鸣器

sbit    LED1  =  P2^0;       //第一个数码管共阴极
sbit    LED3  =  P2^1;       //第三个数码管共阴极
sbit    LED4  =  P2^2;       //第四个数码管共阴极
sbit    LED2  =  P2^5;       //第二个数码管共阴极
sbit    StartKEY = P3^0;     //开始抢答键
sbit    answerKEY = P3^1;    //开始答题键
uchar StartKEYDown;          //抢答键按下标志位
uchar KeyDown ;              //已有按键按下标志位
uchar ClearShake;            //按键消除抖动计时
uint16 BuzzerAlarm;          //蜂鸣器报警1秒钟
uchar ScanningFlag;          //数码管动态扫描控制标志位
uchar ContestTimeCnt;        //为抢答时间计时
uchar AnswerTimeCnt;         //为答题时间计时
uchar AnswerKEYDown;         //答题键按下标志位
uchar AlarmFlag;             //已报警过标志位
uchar ContestOverTime;       //抢答时间到标志位
uchar AnswerOverTime;        //答题时间到标志位
uchar ContestKeyDown;        //抢答键已按下过标志位用来控制系统的清除
uchar NoAnswer;    //没人回答正确报警已经输出过
uchar AlarmControl;         //抢答倒计时还剩10秒钟报警输出
uchar AlarmOutput;          //选手按下抢答键时报警输出控制
#define ContestTime 30      //抢答时间30秒钟
#define AnswerTime 60       //答题时间60秒钟
const uchar SheetLed[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0xff};  //0 1 2 3 4 5 6 7 8 9  不显
//const uchar SheetLed[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
/*void Delay(uint16 i)

{
      while(i--);

} */



void InitWindow(void)
{
  
     LED1 = 1; //初始化的时候所有数码管都不选通
  
     LED3 = 1; //相当于数码管全部不点亮

     LED4 = 1;

  
}

/***********按键扫描程序***************/

void KeyCheck(void)
{

     if(StartKEY == 0) //抢答键按下
   
     if(ClearShake == 5) //定时器中断时间2ms按键消除抖动2*5=10ms
     {   
     
         StartKEYDown = 1; //抢答器按下标志位抢答键按下后开放选手的按键功能否则按下无效

         BEEP = 0;    //抢答键按下蜂鸣器报警通知选手
   
         BuzzerAlarm = 0;//计时清零蜂鸣器报警一秒钟后关闭
   
         ContestTimeCnt = 0;

         AnswerTimeCnt = 0;
  
         ContestKeyDown = 1;

         KeyDown = 0;
  
         AnswerKEYDown = 0;
  
         NoAnswer = 0;

         AlarmFlag = 0;
  
         ContestOverTime = 0;

         AlarmOutput = 0;
     
      }

      if(KeyDown != 0) //有选手按下抢答键否则答题键无效

      if(answerKEY == 0)    //答题键按下
   
       if(ClearShake == 5)   
   
       {   
   
            AnswerKEYDown = 1;
     
            BEEP = 0;
  
        }

       if(BuzzerAlarm == 500) //1000ms时间到

       {
   
           if(StartKEYDown == 1)//抢答键已被按下选手开始抢答
  
           {
   
               BEEP = 1; //关闭报警输出
   
               BuzzerAlarm = 0; //计时清零
      if(KeyDown == 0)  //没有选手按下抢答键
   
                if(ContestOverTime == 0) //倒计时没到30秒钟可以继续计时
   
                 ContestTimeCnt++;  //没有选手按下抢答键抢答时间继续倒计时否则停止
   
  
               if(AnswerKEYDown == 1) //答题键按下
             //BuzzerAlarm = 0; //计时清零
          // ContestTimeCnt=0;
               if(AnswerOverTime == 0)//答题时间没到60秒钟可以继续计时
   
                 AnswerTimeCnt++;
   
                 if(ContestTimeCnt == 30) //30秒钟时间到
   
                 {   
  
                      //ContestTimeCnt = 0;
  
                        ContestOverTime = 1;

                        if(KeyDown == 0) //没有选手按下抢答键
   
                        if(AlarmFlag == 0)//系统还没报过警
   
                        {   
     
                            BEEP = 0;  //报警输出
      
                            AlarmFlag = 1; //已报警标志位
   
                         }
  
                 }
   
                if(AnswerTimeCnt == 60) //答题时间时间到
   
                 if(NoAnswer == 0)
   
                 {   
   
                       AnswerOverTime = 1;
  
                       BEEP = 0;
  
                       NoAnswer = 1;
                 }
  
             }   

        }

       if(KeyDown == 0)
   
        if(ContestTimeCnt > 20)
  
        {   
   
            if((ContestTime - ContestTimeCnt) == 0)
      
                 BEEP = 1;

           else
   
                 BEEP = 0;
   
        }
       if(AnswerTimeCnt > 55)
   
        if((AnswerTime - AnswerTimeCnt) == 0)
     
              BEEP = 1;
  
        else
   
              BEEP = 0;
   
   
        if(AlarmFlag != 1)//30秒倒计时没到可以继续抢答

         if(KeyDown == 0) //没有选手按下抢答键继续扫描

         {  
     
             if(KEY1 == 0)      //抢答键1按下
   
              if(ClearShake == 5)
   
                 KeyDown = 1;   //一旦检测到有一个按键按下停止扫描其它按键
   
  
            if(KEY2 == 0)      //抢答键2按下
   
              if(ClearShake == 5)
                 KeyDown = 2;
   

            if(KEY3 == 0)
               if(ClearShake == 5)   
  
                  KeyDown = 3;   //抢答键3按下
   

           if(KEY4 == 0)
   
                if(ClearShake == 5)   
   
                     KeyDown = 4;   //抢答键4按下


           if(KEY5 == 0)
                if(ClearShake == 5)   
   
                     KeyDown = 5;    //抢答键5按下
   
           if(KEY6 == 0)
   
                if(ClearShake == 5)
     
                     KeyDown = 6;  //抢答键6按下
   
  
           if(KEY7 == 0)
   
                if(ClearShake == 5)
     
                     KeyDown = 7;  //抢答键7按下

  
           if(KEY8 == 0)
   
                if(ClearShake == 5)
   
                    KeyDown = 8;  //抢答键8按下  
       }
      else

      {
   
           if(AlarmOutput == 0)
     
           {
   
                BEEP = 0;  //报警输出
   
                AlarmOutput = 1;
  
            }
      }

      
if(ClearShake > 5)
   
          ClearShake = 0;    //每个按键的消抖计时统一清零
}

/***********数码管显示程序******************/
void LedShow(void)
{
   
     if(StartKEYDown == 1)//抢答键已被按下选手开始抢答

     {   
   
         if(ScanningFlag == 0)//控制数码管轮流显示
   
         {
      
            LED1 = 1;
  
            LED3 = 0; //选中第3个数码管显示抢答倒计时十位
  
            LED4 = 1;
   
            P0 = SheetLed[(ContestTime - ContestTimeCnt)/10];  //动态扫描时间为2ms

            ScanningFlag = 1;
   
         }
        else if(ScanningFlag == 1)
   
        {
      
            LED1 = 1;
   
            LED3 = 1;
   
            LED4 = 0;
  
            P0 = SheetLed[(ContestTime - ContestTimeCnt)%10];
  
            ScanningFlag = 2;
   
         }

    else if(ScanningFlag == 2)  
      
   
            {
         
                if(AnswerKEYDown == 1)
   
                {   
        //P0 = 0xff;
     
                    LED1 = 1;
   
                    LED4 = 1;
   
                    LED3 = 0;   //答题倒计时十位
   
                    P0 = SheetLed[(AnswerTime-AnswerTimeCnt)/10];
      
                }
   
                ScanningFlag = 3;
   
           }
          else if(ScanningFlag == 3)
   
          {
      
               if(AnswerKEYDown == 1)
   
               {   
                    LED1 = 1;
   
                    LED3 = 1;
   
                    LED4 = 0;  //答题倒计时个位
     
                    P0 = SheetLed[(AnswerTime-AnswerTimeCnt)%10];
     
                }
  
                ScanningFlag = 4;
   
          }
          else if(ScanningFlag == 4)
   
          {
   
              ScanningFlag = 0;
   
              switch(KeyDown)
   
             {
     
                  case 0:
      
                                 LED3 = 1;
      
                                 LED4 = 1;
                                 LED1 = 0;
      
                                 P0 = SheetLed[10];//没有选手按下按键第一个数码管不显示
   
                                 break;
     
                  case 1:
                  
      
                                 LED3 = 1;
      
                                 LED4 = 1;
   
                                 LED1 = 0;
      
                                 P0 = SheetLed[1];
   
                                break;
     
                 case 2:
      
                                LED3 = 1;
      
                                LED4 = 1;
                                LED1 = 0;
      
                                P0 = SheetLed[2];
   
                                break;
     
                 case 3:
      
                                LED3 = 1;
      
                                LED4 = 1;
   
                                LED1 = 0;
      
                                P0 = SheetLed[3];
   
                                break;
     
                case 4:
      
                                LED3 = 1;
      
                                LED4 = 1;
   
                                LED1 = 0;
      
                                P0 = SheetLed[4];
                                break;
     
               case 5:
     
                                LED3 = 1;
     
                                LED4 = 1;
   
                                LED1 = 0;
      
                                P0 = SheetLed[5];
   
                                break;
   
               case 6:
                                LED3 = 1;
      
                                LED4 = 1;
   
                                LED1 = 0;
      
                                P0 = SheetLed[6];
   
                                break;
     
               case 7:
      
                                LED3 = 1;
      
                                LED4 = 1;
  
                                LED1 = 0;
     
                                P0 = SheetLed[7];
   
                                break;
   
              case 8:
      
                                LED3 = 1;
      
                                LED4 = 1;

                                LED4 = 1;
  
                                LED1 = 0;
      
                                P0 = SheetLed[8];
   
                                break;
        
        }
   
   
     }
   
  }
}

/**********定时器0初始化函数*****************/
void Init_timer()
{

     TMOD=0x01;    //0000 0001 定时器0在模式1下工作16位计数

     TH0=63536/256; //定时器0初值 定时2000us

     TL0=63536%256;   
     ET0=1;    //使能定时器0中断

     EA=1;     //使能总中断

     TR0=1;    //开始计时
}
/****************************************************************************
* 名称 timer0()
* 功能 定时器1每2000us中断一次。
* 入口参数
****************************************************************************/
void timer0(void) interrupt 1  
{
     EA =0; //关总中断

     TR0=0; //关定时器中断  

     TMOD=0x01;    //0000 0001 定时器0在模式1下工作16位计数
     TH0=63536/256; //重新装初值
   
     TL0=63536%256;

     TR0=1;    //开中断

     EA=1;

     ClearShake++;

     BuzzerAlarm++;

     LedShow(); //数码管显示
  
}

void main(void)
{
  
     Init_timer();//定时器初始化
  
     InitWindow();
  
     for(;;)

     {
   
         KeyCheck();

      
  
      }
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:70499 发表于 2014-12-18 11:59 | 只看该作者
看看看

回复

使用道具 举报

板凳
ID:154754 发表于 2016-12-14 17:05 | 只看该作者
学习了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表