|
基于单片机的八路抢答器
一、主要内容
通过利用数码管显示,并自动复位的思路,运用单片机的运行产生输出信号,通过数码管显示对应的通道,实现了一个以单片机为核心的8路抢答器,
并且具有查看选手分数和进行加减分的功能。
二、具体操作
2、主持人按下开始键选手等待时间计完听到滴声后才可以抢答,若提前抢到则
视为犯规。
3、抢答成功后别的选手再抢到也是没有用的。
4、显示屏上显示哪位选手抢到,并开始对答题时间进行倒计时。
5、显示答题时间,在答题时间小于 5S 时报警电路会发生作用。
7、当主持人按下 RESET 键则进行下一轮的比赛。
二、程序用什么软件查看?
打开程序的软件是Keil
单片机源程序如下:
- #include <reg51.h>
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- sbit smg1=P2^0; //定义数码管第一位
- sbit smg3=P2^2; //定义数码管第三位
- sbit smg4=P2^3; //定义数码管第四位
- sbit keyks=P3^5; //定义开始按键
- sbit keytz=P3^4; //定义停止按键
- sbit keyqc=P3^3; //定义清除按键
- sbit beep=P3^6; //定义蜂鸣器
- uchar k;
- uchar keyvalue=0;
- uint a;
- int djs=20,js=0; //djs和bt是初始倒计时时间,可修改
- int table[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- int zhunbei[] = {0x92,0x99,0xb0,0xa4,0xf9,0xc0};//准备抢答
- int fenshu[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- char fs[8];
- uchar mode=0; //主持人的按键模式
- // mode=0:显示选手1的分数 mode=1:显示选手2的分数....../////////
- void delayzb(uint z)//准备抢答延时
- {
- uint x,y;//局部变量定义
- for(x = z;x>0;x--)//此for循环100次
- for(y = 144;y>0;y--);//此for循环144次,100*144次循环正好是100ms.
- }
- void delay()
- {
- uchar m,n,s;
- for(m = 20;m>0;m--);
- for(n = 20;n>0;n--);
- for(s = 248;s>0;s--);
- }
- void delayms(uint z)
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void Getch () //取键值函数
- {
- //keyvalue=0;
- P1=0xf0; //先对P3 置数 列扫描
- if(P1!=0xf0) //判断是否有键按下
- {
- delay(); //延时,软件去干扰
- if(P1!=0xf0) //确认按键按下
- {
- switch (P1) //判断键值(哪一列被按下)
- {
- case 0xe0: keyvalue=1; break; //第一列被按下
- case 0xd0: keyvalue=2; break; //第二列被按下
- case 0xb0: keyvalue=3; break; //被三列被按下
- case 0x70: keyvalue=4; break; //被四列被按下
- }
- P1 = 0x0f; //行扫描
- switch (P1) //判断哪一行被按下
- {
- case 0x0e: keyvalue=keyvalue; break; //第一行被按下
- case 0x0d: keyvalue=keyvalue + 4; break; //第二行被按下
- case 0x0b: keyvalue=keyvalue + 8; break; //第三行被按下
- case 0x07: keyvalue=keyvalue + 12; break; //第四行被按下
- }
- while (P1 != 0x0f); //松手检测
- }
- }
- }
- void Timer0_init() //定时器0初始化
- {
- js=0;
- TMOD=0x01; //TR0=1;//IT1=1; //T0为定时器方式1 //EX1=1;
- TH0=0x4c; //每50ms溢出一次
- TL0=0x00;
- ET0=1;
- EA=1;
- }
- void timer0() interrupt 1 using 1 //定时器0中断服务函数
- {
- TF0=0;
- TH0=0x4c; //每50ms溢出一次
- TL0=0x00; //赋初值
- js++;
- if(js==20) //20*50=1000ms=1s
- {
- js=0;
- djs--; //产生1s的倒计时
- }
- if(djs==5)
- {
- beep = 0; //倒计时后5s报警
- delay();
- beep = 1;
- delay();
- }
- if(djs==0)
- {
- P2 = 0xff;
- TR0=0; //倒计时结束,关闭定时器
- }
- }
- void djsxs() //显示倒计时函数
- {
- int shi,ge;
- shi=djs/10;
- ge=djs%10; // 将倒计时时间分成高低位
- P2=0XFF;
- smg4 = 0;
- P0=table[ge];
- smg4 = 0;
- delayms(2);
- P2=0XFF;
- smg3 = 0;
- P0=table[shi];
- smg3 = 0;
- delayms(2);
- P2=0XFF;
- }
- void djsxs22() //显示- --
- {
- P2=0XFF;
- P0=0xbf;
- smg1 = 0;
- delayms(3);
- P2=0XFF; //第一位数码管显示-
- P0=0xbf;
- smg3 = 0;
- delayms(3); //第三位数码管显示-
- P2=0XFF;
- P0=0xbf;
- smg4 = 0;
- delayms(3);
- P2=0XFF; //第四位数码管显示-
- }
- void playerxs()
- {
- P0=table[keyvalue];
- smg1=0;
- delayms(3);
- smg1=1;
- } //第一位数码管显示
- void main()
- {
- int djs1=20;
- Timer0_init(); //初始化定时器中断
- beep=1; //蜂鸣器不响
- djs=20; //倒计时赋值
-
- while(1)
- {
- LOOP1:
- Getch();
- djs=djs1;
- djsxs22(); //LOOP1是标号,显示 - --
- keyvalue = 0;
- // beep=1; //蜂鸣器不响
- djs=20; //倒计时赋值
- TR0 = 0;
-
-
- if(keyks==0)//开始按键
- {
- beep=0;//蜂鸣器响
- delayms(3); //去除按键抖动
- if(keyks==0) //确定开始按下
- {
-
- while(!keyks); //松手检测
- {
- beep=1;
- for(a = 0;a<6;a++) //5s倒计时准备抢答
- {
- P2 = 0xf7;//1111 0111 //第四位数码管显示5s倒计时
- P0 = zhunbei[a];
- delayzb(800);
- P2 = 0xff;
- }
- }
-
- while(1)
- {
- Getch();
-
- if(keyqc == 0)
- {
- delayms(3); //去除抖动
- if(keyqc == 0)
- {
- while(!keyqc); //如果按下清除键,则回到- --状态
- goto LOOP1; //goto语句,回到loop1表号处
- }
- }
-
-
-
-
- /*以下是八个选手抢答,key1表示1号选手,依次类推,注释只写第一位选手,其他和第一个完全一致*/
-
- if((keyvalue>=1)&&(keyvalue<=8)&&(TR0==0)) //在定时器关闭状态下,key1==0 则说明1号选手按下按
- {
- beep=0; //蜂鸣器响
-
- //while(!key1); //去除按键抖动后,重新在判断,是否确实按下
- beep=1; //蜂鸣器不响
- TR0=1; //定时器开始
- while(1)
- {
- mode = keyvalue;
- playerxs(); //显示选手编号
- djsxs(); //显示剩余倒计时时间
- //keyvalue = 1;
-
- if(keyqc == 0)
- {
- delayms(3); //去除抖动
- if(keyqc == 0)
- {
- while(!keyqc); //如果按下清除键,则回到- --状态
- goto LOOP1; //goto语句,回到loop1表号处
- }
- }
- if(keytz == 0) //暂停按下按下
- {
- delayms(3); //去除抖动
- if(keytz == 0) //再次判断是否按下复位按键
- {
- while(!keytz) //如果按下复位键,则回到- --状态
- TR0=0;
- }
- }
- if(keyks == 0)//开始按键
- {
-
- beep=0;//蜂鸣器响
- delayms(30); //去除按键抖动
- if(keyks == 0) //确定开始按下
- {
- while(!keyks); //松手检测
- {
- beep=1; //蜂鸣器不响
- delay();
-
- TR0 = 1;
- }
- }
- }
- if(djs == 0)
-
- break;
-
- }
- }
-
- if (mode!=0)
- {
- TR0 = 0;
-
- while(1)
- {
- P0=table[mode];
- smg1=0;
- delayms(3);
- smg1=1; //显示选手编号
- P0=table[fs[mode]];
- smg4=0;
- delayms(3);
- smg4=1;
- Getch();
- if(keyvalue == 9)
- {
- keyvalue = 0;
- mode++;
- if(mode>8)
- {
- mode=0;
- }
- }
- else if(keyvalue == 10) //加分
- {
- keyvalue = 0;
- fs[mode]++;
- if(fs[mode] == 10)
- fs[mode] = 9;
- }
复制代码
|
|