8路抢答器设计难度分:9基本要求:8个选手抢答按键,1个主持人按键,4只LED数码管显示。系统复位状态LED显示“00 00”;主持人按下按键则抢答开始,系统显示3秒抢答时间倒计时,计时到无人抢答则系统发出报警后自动复位;8个选手最先按下者抢答成功,显示选手编号和答题时间10秒,支持人发出开始作答指令同时按下主持人键,答题时间开始倒计时并显示,若选手回答结束之后主持人按下主持人键复位系统,若倒计时结束选手未回答问题系统发出报警后自动复位。扩展要求:增加1个“√”键和1个“×”键,只在10秒回答时间内有效,若选手回答正确,主持人按下“√”键彩灯闪烁,若选手回答错误,主持人按下“×”键发出低沉报警音;系统复位后抢答开始前,选手不得提前抢答,否则发出违例报警,显示违例选手编号,由主持人复位系统;可修改答题时间。
仿真原理图如下(proteus8.10版本的仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- //头文件声明
- #include<reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
-
- //code uchar seven_seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- code uchar seven_seg[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
- code uchar seven_bit[] = {0xfe,0xfd,0xfb,0xf7};
- sbit run_key = P3^2; //启动按键
- sbit buzzer = P3^5; //报警
- sbit add_key = P3^6; //加
- sbit dec_key = P3^7; //减
- uchar player; //定义选手按键的键值参数
- uint player_num = 0; //选手号
- uchar now_time = 0; //默认复位时间0S
- uchar next_time=10; //默认答题时间10s
- bit run_flag = 0; //主持人按下开始标志位
- bit time_off = 0; //倒计时时间到,或者开始有人抢答成功标志位
- uint Count_A = 0; //定时器计数参数
- uint Count_B = 0; //定时器计数参数
- void delay(uint ms) //延时函数
- {
- uint i,j;
- for(i=ms;i>0;i--)
- for(j=110;j>0;j--);
- }
- void dispaly(uint a,uint b) //a为选手号码,b为时间
- {
- P2=seven_bit[0];
- P0=seven_seg[a]; //显示选手号
- delay(5);
- P2=seven_bit[1];
- P0=0x40; //显示横杠
- delay(5);
- P2=seven_bit[2];
- P0=seven_seg[b/10]; //显示倒计时时间
- delay(5);
- P2=seven_bit[3];
- P0=seven_seg[b%10];
- delay(5);
- P2=0xff;
- }
- void keyScan() //按键子程序
- {
- if(run_key==0) //如果启动按键按下
- {
- delay(5); //消抖
- if(run_key==0)
- {
- if(now_time!=next_time)
- {
- if(player_num!=0)
- {
- now_time=0; //答题结束按键按键复位
- player_num=0;
- time_off=0;//复位选手按下标志
- }
- else
- {
- player_num=0;
- run_flag=1; //设置模式调整
- buzzer=0;//0.5S声音
- now_time=3;
- TR0=1; //开启定时器
- TR1=1;
- }
- }
- else
- {
- buzzer=0;//0.5S声音
- TR0=1; //开启定时器
- TR1=1;
-
- }
- }
- while(run_key==0); //等待按键放开
- }
- if(run_flag==0&&time_off==0) //只有没开始抢答的时候可以加减
- {
- if(add_key==0)
- {
- delay(5);
- if(add_key==0)
- {
- next_time++; //时间加上去
-
- }
- while(add_key==0) dispaly(player_num,next_time); //显示
- }
- if(dec_key==0)
- {
- delay(5);
- if(dec_key==0)
- {
- next_time--; //时间减下来
-
- }
- while(dec_key==0) dispaly(player_num,next_time); //显示
- }
- }
- }
- void EX_Init()
- {
- /*********初始化定时器/外部中断**********/
- TMOD = 0x11; //10ms
- TH0 = 0x0D8;
- TL0 = 0x0F0;
- TH1 = 0x0D8;
- TL1 = 0x0F0;
- IE = 0x8b; //IE = 0x85;
- IT0 = 1;
- IT1 = 1;
- PX0 = 1;
- TR0 = 0; //关闭定时器
- TR1 = 0;
- }
- void main(void)
- {
- EX_Init(); //初始化
- buzzer=1;
- P2=0xff;
- P1=0xff;
- P0=0xff;
- while(1) //死循环
- {
- keyScan(); //按键程序
- dispaly(player_num,now_time); //显示
- }
- }
- void Time0() interrupt 1
- {
- TH0 = 0x0D8; //10ms
- TL0 = 0x0F0;
-
- if(run_flag==1) //如果开始抢答
- {
- player=P1; //读取端口
-
- switch(player)
- {
- case 0xfe:player_num=1;run_flag=0;time_off=1;TR0=0;TR1=0;now_time=next_time;break; //为第一个选手按下时,选手号=1,定时器停止,时间十秒
- case 0xfd:player_num=2;run_flag=0;time_off=1;TR0=0;TR1=0;now_time=next_time;break;
- case 0xfb:player_num=3;run_flag=0;time_off=1;TR0=0;TR1=0;now_time=next_time;break;
- case 0xf7:player_num=4;run_flag=0;time_off=1;TR0=0;TR1=0;now_time=next_time;break;
- case 0xef:player_num=5;run_flag=0;time_off=1;TR0=0;TR1=0;now_time=next_time;break;
- case 0xdf:player_num=6;run_flag=0;time_off=1;TR0=0;TR1=0;now_time=next_time;break;
- case 0xbf:player_num=7;run_flag=0;time_off=1;TR0=0;TR1=0;now_time=next_time;break;
- case 0x7f:player_num=8;run_flag=0;time_off=1;TR0=0;TR1=0;now_time=next_time;break;
- case 0xff:break; //全高电平-无人按下,退出
- default:player_num=9; break; //出现其它情况,显示9
- }
- }
- }
- void Time1() interrupt 3
- {
- TH1 = 0x0D8;
- TL1 = 0x0F0; //10ms
- Count_A++;
- Count_B++;
- if(Count_B<50) //500ms的蜂鸣器提示
- buzzer=0;
- else buzzer=1;
-
- if(Count_A==100) //每秒钟减一,倒计时
- { Count_A=0;
- now_time--; //当前倒计时时间 --
- if(now_time<=0) //倒计时结束(到0),那么开始报警,其它复位
- { now_time=0;run_flag=0;TR0=0;TR1=0;time_off=1;buzzer=0; delay(1200);buzzer=1;}
- }
- }
复制代码
Keil代码与Proteus8.10仿真下载:
抢答器.rar
(94.5 KB, 下载次数: 80)
|