规则:
以15秒为倒计时,数码管会显示倒计时。
倒计时不为0,选手可以抢答。
一旦有第一个抢答后,并且倒计时会停止,数码管显示第一个抢答选手的号码,其他选手再抢答无效
如果倒计时为0都没有人抢答,那么数码管会卡在0等裁判恢复,重新进入倒计时15秒的抢答环节。
如果有人抢答了,已经答题了,需要进入下一轮抢答,那么也要裁判恢复,重新进入倒计时15秒的抢答环节。
#include<reg51.h>
char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80
,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//把数组放入ROM中
sbit con1=P3^0;//只显示15秒
sbit con2=P3^1;
sbit caipan=P1^0;//裁判
char tmp=0,sec=15,num=0;//-128-127 ,num是选手号码
void delay(char ms)
{
char x,y;
for(x=ms;x>0;x--)
for(y=110;y>0;y--);
}
void init()
{
//定时器的初始化
TMOD=0x01;//定时器方式一的设置
TR0=1;//time run
ET0=1;//定时器的使能
EA=1; //总中断打开
TH0=(65536-50000)/256;//50ms定时一次,高8位
TL0=(65536-50000)%256;//50ms定时一次,低8位
IT0=1;
EX0=1;
}
void display(char s)//把显示的功能封装成子函数
{
P2=table[s/10];
con1=1;
delay(10);
con1=0;
P2=table[s%10];
con2=1;
delay(10);
con2=0;
}
main()
{
init();
while(1)
{
if(caipan==0)//裁判按下按钮
{
sec=15;
EA=1;//开启定时与外部抢答中断
}
if(sec==0)//如果倒计时为0,那么让数码管卡在0
{
EA=0;//总中断关闭,定时器中断,也不能抢答
}
display(sec);
}
}
void ex0() interrupt 0//INTO中断信号是0
{
EA=0;//关闭总中断,让定时器不能进入中断,第一个选手按下后,第二个选手按下无效
//总中断关闭后,void ex0() interrupt 0这一个中断函数也不能引发中断
//第一个选手能进来中断,其他的选手将不能进入中断
if((P1&0xfe)!=0xfe)//检测有没有按下按钮,&0xfe是屏蔽P1.0位
{
switch(P1&0xfe)
{
case 0xfc:num=1;break;//选手1号按下
case 0xfa:num=2;break;//选手2号按下
case 0xf6:num=3;break;//选手3号按下
case 0xee:num=4;break;//选手4号按下
case 0xde:num=5;break;//选手5号按下
case 0xbe:num=6;break;//选手6号按下
case 0x7e:num=7;break;//选手7号按下
}
}
sec=num;//sec是负责显示变量
}
void time0()interrupt 1//interrupt是中断标志号1一定要与中断类型对应上,50ms进入一次中断函数
//CPU接收到了中断的请求后,会自动执行这个函数,不要在main函数中调用
//定时器与延时相比,延时是需要调用,定时就像后台自动执行
//定时器的CPU工作效率比较高
{
TH0=(65536-50000)/256;//50ms定时一次,高8位
TL0=(65536-50000)%256;//50ms定时一次,低8位
//如果不重置TH0和TL0,那下一轮的中断就变成了65.536ms
tmp++;//每隔50ms加一,加到多少就变成1s,20次
if(tmp==20)//这逻辑成立,代表是1s到
{
tmp=0;//计算下一轮的1s,让tmp置0
sec--; //抢答器的倒计时
}
}//时间处理