/*八路抢答器-----能够显示抢答、回答时间倒计时,能够调节抢答、回答时间,能够报警犯规抢答,可以计分,可以实现软复位*/
/*桂林电子科技大学*信息与通信学院*电子科学与技术*/
/*此程序仅供参考!!恳请自重*/
/*本人博客:http://blog.sina.com.cn/13302xiaoqiao */
/*欢迎交流*/
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit fmq=P3^6;
sbit Key_Start=P3^4;//开始键,时间设置时+
sbit Key_Stop=P3^5;//停止键,时间设置时-
sbit Key_Restart=P3^0;//复位键
sbit Key_set_Q=P3^2;//抢答时间设置键
sbit Key_set_H=P3^3;//回答时间设置键
sbit led=P3^7;//抢答LED提示
uchar code table[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6,0xf0,0xb6};//段码表
uchar code table_char[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xc7,0xc0,0x92,0x86,0xbf,0xb7,0xff,0xb9,0x8f};//0-9 L O S E -
uchar table_score[9]={0,50,50,50,50,50,50,50,50};//记分数组,初设值50分
void delay(uint z);//延时函数声明
void init();//初始化函数声明
void display(uchar XuanShou,uchar time);//显示数字函数声明
void display_char(uchar char_1,uchar char_2,uchar char_3,uchar char_4 );//显示字符函数声明
void display_set(uchar char_1,uchar time,uchar char_2);//时间设置闪动显示函数声明
void display_score(uchar xs_num);//分数查询显示函数
void beep();//蜂鸣器函数
void beep_last();//蜂鸣器特殊报警
void LED();//提示灯函数
uchar QiangDa_time,HuiDa_time,QiangDa_time_temp=20,HuiDa_time_temp=30;//抢答时间、回答时间变量
uchar count_0,count_1;//定时中计数用的
uint shan_count=0;//闪动显示计数用
void beep_x()
{
uint x=0;
uchar d1,d2;
for(x=0;x<300;x++)
{
fmq=~fmq;
for(d1=0;d1<10;d1++)
for(d2=0;d2<5;d2++);
}
}
void main()
{
uchar AnJian,ShuJu,XuanShou_num;
Top:init();//初始化
XuanShou_num=1;//为分数查询做好准备
beep();
while(1)
{
display(10,0);//显示一杠
ShuJu=P1;
if(ShuJu!=0xff)//犯规抢答!!
{
// delay(10);
// if(ShuJu!=0xff)
// {
AnJian=ShuJu;
switch(AnJian)//取出选手编号
{
case 0xfe : XuanShou_num=1;break;//1111 1110
case 0xfd : XuanShou_num=2;break;//1111 1101
case 0xfb : XuanShou_num=3;break;//1111 1011
case 0xf7 : XuanShou_num=4;break;//1111 0111
case 0xef : XuanShou_num=5;break;//1110 1111
case 0xdf : XuanShou_num=6;break;//1101 1111
case 0xbf : XuanShou_num=7;break;//1011 1111
case 0x7f : XuanShou_num=8;break;//0111 1111
default : goto LOSE;//无法显示了,有两个以上的键同时按下了!!不过这种概率相当小
}
while(1)
{
display_char(13,14,14,XuanShou_num);//闪动显示犯规选手并且报警
if(shan_count==50)
{
beep();
}
if(Key_Stop==0)
{
delay(10);
if(Key_Stop==0)
{
beep();
table_score[XuanShou_num]--;//扣分
}
}
while(!Key_Stop)
{
display_char(14,14,1,16);//按键不放开的情况下显示-1
shan_count=1;//调用的是闪动显示函数,但是不让其闪动
}
if(Key_Restart==0)
{
delay(10);
if(Key_Restart==0)
{
beep();
goto Top;//热复位
}
}
}
// }
}
if(Key_Start==0)
{
delay(10);
if(Key_Start==0)//主持人按下抢答键,抢答正式开始!
{
QiangDa_time=QiangDa_time_temp;
HuiDa_time=HuiDa_time_temp;
beep();
TR1=1;//抢答时间开始倒计时
break;//跳出犯规抢答查询循环
}
}
//一下为查分程序测试
if(Key_Stop==0)
{
delay(10);
if(Key_Stop==0)//进入分数查询显示
{
beep();
while(!Key_Stop);
while(1)
{
display_score(XuanShou_num);
if(Key_Start==0)
{
delay(10);
if(Key_Start==0)
{
XuanShou_num++;
if(XuanShou_num==9) XuanShou_num=1;
}
}
while(!Key_Start);//等待按键释放
if(Key_Stop==0)
{
delay(10);
if(Key_Stop==0)
{
XuanShou_num--;
if(XuanShou_num==0) XuanShou_num=8;
}
}
while(!Key_Stop);//等待按键释放
if(Key_Restart==0)
{
delay(10);
if(Key_Restart==0)
{
beep();
goto Top;//热复位
}
}
}
}
}
}
while(1) //查询是否有按键按下,进入抢答循环
{
display(10,QiangDa_time);//显示抢答倒计时
if(QiangDa_time==0)
{
// beep();
TR1=0;//关闭定时器1
LOSE: while(1)
{
display_char(10,11,12,13); //显示lose 字符
if(Key_Restart==0)
{
delay(10);
if(Key_Restart==0)//热复位键,从头开始下一轮
{
beep();
goto Top;
}
}
}
}
ShuJu=P1;//把P1口的数据送给变量
if(ShuJu!=0xff)//有按键按下
{
// delay(10);
// if(ShuJu!=0xff)//确定有按键按下
// {
AnJian=ShuJu;//传递数据扫描值
// TR0=1;//启动定时器0
TR1=0;//关闭定时器1
break;//不再进行查询是否有按键按下了
// }
}
}
switch(AnJian)//取出选手编号
{
case 0xfe : XuanShou_num=1;beep();LED();break;//1111 1110
case 0xfd : XuanShou_num=2;beep();LED();break;//1111 1101
case 0xfb : XuanShou_num=3;beep();LED();break;//1111 1011
case 0xf7 : XuanShou_num=4;beep();LED();break;//1111 0111
case 0xef : XuanShou_num=5;beep();LED();break;//1110 1111
case 0xdf : XuanShou_num=6;beep();LED();break;//1101 1111
case 0xbf : XuanShou_num=7;beep();LED();break;//1011 1111
case 0x7f : XuanShou_num=8;beep();LED();break;//0111 1111
default : goto LOSE;//无法显示了,有两个以上的键同时按下了!!不过这种概率相当小
}
TR0=1;//启动定时器0(在这里启动比在前面好)
while(1)
{
display(XuanShou_num,HuiDa_time);//显示选手编号和回答倒计时
if(HuiDa_time==0)
{
TR0=0;//关闭定时器0
goto LOSE;//跳到显示lose字符那里
}
if(Key_Stop==0)
{
delay(30);
if(Key_Stop==0)//停止键按下
{
beep();
TR0=0;//关闭定时器0,选手开始回答
while(!Key_Stop);
while(1) //在显示选手回答倒计时时只有在stop按键按下时,才可按复位键
{
display(XuanShou_num,HuiDa_time);//显示选手编号和回答倒计时
if(Key_Start==0)
{
delay(10);
if(Key_Start==0)
{
beep();
table_score[XuanShou_num]++;//加分
}
}
while(!Key_Start)
{
display_char(17,18,1,16);//按键不放开的情况下显示+1
shan_count=1;//调用的是闪动显示函数,但是不让其闪动
}
if(Key_Stop==0)
{
delay(10);
if(Key_Stop==0)
{
beep();
table_score[XuanShou_num]--;//扣分
}
}
while(!Key_Stop)
{
display_char(14,14,1,16);//按键不放开的情况下显示-1
shan_count=1;//调用的是闪动显示函数,但是不让其闪动
}
if(Key_Restart==0)
{
delay(10);
if(Key_Restart==0)//热复位键,从头开始下一轮
{
beep();
goto Top;
}
}
}
}
}
// else
/* if(Key_Restart==0)
{
delay(10);
if(Key_Restart==0)//热复位键,从头开始下一轮
{
beep();
goto Top;
}
} */
}
}
void delay(uint z)//1ms基准延时
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void init()//初始化函数
{
// P1=0xff
EA=1;//开总中断;
TMOD=0x11;//定时器工作方式1,16位定时计数器
TH0=(65536-50000)/256;//50us
TL0=(65536-50000)%256;
ET0=1;//开定时器0中断(暂时不启动定时器)
// TMOD=0x01;//定时器工作方式1,16位定时计数器
TH1=(65536-50000)/256;//50us
TL1=(65536-50000)%256;
ET1=1;//开定时器0中断(暂时不启动定时器)
EX0=1;//启动外中断0
EX1=1;//启动外中断1
P1=0xff;//读P1口的数据要先置1准备
count_0=0;//定时器中的计数清零
count_1=0;
shan_count=0;
}
void display(uchar XuanShou,uchar time)//显示数字的函数
{
P2=0x7f;//0111 1111最后一位数码管亮
P0=table[XuanShou];//选手编号
delay(1);
P2=0x7f;//0111 1111
P0=0xff;//消余辉
delay(1);
P2=0xdf;//1101 1111
P0=table[time%10];//时间的个位
delay(1);
P2=0xdf;//0111 1111
P0=0xff;//消余辉
delay(1);
P2=0xef;// 1110 1111
P0=table[time/10];//时间的十位
delay(1);
P2=0xef;//0111 1111
P0=0xff;//消余辉
delay(1);
}
void display_char(