#include
#define Boolean unsigned char
#define SegCode P0 //数码管段数据
#define Seg(x) (1<
#define Nag(x) (~x)
#define SegSel P1 //数码管段选
#define BntVal P2 //按键定义
#define true 1
#define false 0
***it Up=P3^0;
***it Down=P3^1;
***it Set1=P3^2;
***it Set2=P3^3;
***it Confirm=P3^4;
***it LED=P3^5;
***it Statue=P3^6;
unsigned char Qdtime,Hdtime;
unsigned char STAR;
//毫秒级延时函数。最大延时为65ms
void delay_us(unsigned int us)
{
Statue = TF1;
//TMOD = 0x10;//定时器工作于模式1
TR1=0;//关闭定时器1
TH1=(65536-us)/256;
TL1=(65536-us)%256;
TR1 = 1 ; // 开启定时器1
while(!TF1);//等待定时器溢出
Statue = TF1;
TF1 = 0;
TR1 = 0 ; //关闭定时器
}
//七段数码管显示函数
//DisDat:显示数据缓冲区
//SegNum:数码管段数
Boolean Seg7Dispaly(unsigned char *DisDat,unsigned char SegNum)
{
unsigned char i;
if(SegNum>8) return false;//数码管段数超过8位,即返回错误
for(i = 0 ; i < SegNum ; i ++)
{
SegSel = Seg(i);
SegCode = 0x80|(*DisDat);
DisDat ++ ;
delay_us(1000);
SegSel = 0x00;
}
return true;
}
//抢答键值检测
unsigned char BottonVal(void)
{
unsigned char Bnt_temp,ValRnt;
Bnt_temp = BntVal;
delay_us(10000);
Bnt_temp = BntVal;
switch(Bnt_temp)
{
case 0xFF:ValRnt = 0;break;//没有按键按下
case 0xFE:ValRnt = 1;break;
case 0xFD:ValRnt = 2;break;
case 0xFB:ValRnt = 3;break;
case 0xF7:ValRnt = 4;break;
case 0xEF:ValRnt = 5;break;
case 0xDF:ValRnt = 6;break;
case 0xBF:ValRnt = 7;break;
case 0x7F:ValRnt = 8;break;
default: ValRnt = 9;break;//错误信息
}
return ValRnt;
}
//初始化外部中断
void InitDevices(void)
{
EA = 0 ;//关闭全局中断
IT0 = 1;//外部中断0使用下降沿中断
IT1 = 1;//外部中断1使用下降沿中断
TMOD= 0x11;//定时器0工作于模式1 ,定时器1工作于模式1
ET0 = 1 ;
EX0 = 1 ;
EX1 = 1 ;
EA = 1;
}
//外部中断0中断服务函数 设置抢答时间
void SetQianDaTime(void) interrupt 0
{
STAR|=0x80;//标志置位
}
//外部中断1中断服务函数 设置回答时间
void SetHuiDaTime(void) interrupt 2
{
STAR|=0x40;//标志置位
}
//定时器0中断服务函数 中断时间50ms
void SecoundCount(void) interrupt 1
{
STAR=STAR+1;//标志置位
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
}
Boolean ConfirmVal(void)
{
Boolean rnt;
rnt = false;
if(!Confirm)//检测出0
{
delay_us(10000);
if(!Confirm){rnt = true ;while(!Confirm);}//等待按键释放
else rnt = false;
}
else rnt = false;
return rnt;
}
//查询设置按键状态
unsigned char QueryKeyValue(void)
{
unsigned char KeyVal;
KeyVal = 0 ;
if(!Up)//检测Up被按下
{
delay_us(10000);
if(!Up){KeyVal = 1 ;while(!Up);}
else KeyVal = 0 ;
}
else KeyVal = 0;
if(!Down)//检测Down被按下
{
delay_us(10000);
if(!Down){KeyVal = 2 ;while(!Down);}
else KeyVal = 0 ;
}
else KeyVal = 0;
return KeyVal;
}
//设置时间
//Disdat:显存首地址
//Asctable:字符表地址
void SetParaTime(unsigned char *Disdat,unsigned char *Asctable)
{
if(STAR&0x80)//设置抢答时间
{
STAR&=~0x80;
while(!ConfirmVal())//确定键未被按下
{
switch(QueryKeyValue())
{
case 0:LED=1;break;
case 1:Qdtime=(Qdtime++)%100;break;
case 2:Qdtime=(Qdtime--)%100;break;
default:LED=~LED;break;
}
Disdat[2]=Asctable[Qdtime/10];
Disdat[3]=Asctable[Qdtime%10];
Seg7Dispaly(Disdat,4);
}
}
if(STAR&0x40)//设置回答时间
{
STAR&=~0x40;
while(!ConfirmVal())
{
switch(QueryKeyValue())
{
case 0:break;
case 1:Hdtime=(Hdtime++)%100;break;
case 2:Hdtime=(Hdtime--)%100;break;
}
Disdat[2]=Asctable[Hdtime/10];
Disdat[3]=Asctable[Hdtime%10];
Seg7Dispaly(Disdat,4);
}
}
}
//清除显存区数据
void ClearSegBuff(unsigned char *buf)
{
buf[0]=0xFF;buf[1]=0xFF;
buf[2]=0xFF;buf[3]=0xFF;
}
//显示状态显示
//sta:显示状态选择。1:正常显示。0为闪烁显示。
//K:闪烁时标
void DisStatueSel(unsigned char *Di***uf,unsigned char sta,unsigned char K)
{
if(sta) Seg7Dispaly(Di***uf,4);//正常显示
else
{
if(K<=10) Seg7Dispaly(Di***uf,4);//正常显示
else Seg7Dispaly(Di***uf,2);//显示前两段
}
}
//选手分数设置函数
//返回值:true:分数设置完成。false:分数未设置。
Boolean PlayersScore(unsigned char Pnum,unsigned char *Score)
{
Boolean rnt;
rnt = false;
switch(QueryKeyValue())
{
case 0:rnt = false;break;
case 1:{Score[Pnum-1]++;rnt = true;}break; //回答正确,加分
case 2:{Score[Pnum-1]--;rnt = true;}break; //回答错误,减分
default:rnt = false;break;
}
if(ConfirmVal()) rnt = true;//分数不加减
else rnt = false;
return rnt;
}
//主函数
void main(void)
{
unsigned char AscTable[]={0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};
unsigned char DisBuff[4]={0x40,0x40,0x40,0x40};
unsigned char score[8]={5,5,5,5,5,5,5,5};//初始分数
unsigned char Qdtemp,Hdtemp,Btval,K;
Boolean Confirmval;
STAR = 0x00 ;//初始化
Qdtime = 12 ;
Hdtime = 12 ;
K = 0;
Confirmval=false;
InitDevices();
ClearSegBuff(DisBuff);
while(1)
{
SetParaTime(DisBuff,AscTable);//设置时间参数
if(ConfirmVal())//主持人按下抢答键
{
Qdtemp = Qdtime;Hdtemp = Hdtime;
TR0 = 1;
while(Qdtemp&&Hdtemp&&!Confirmval)//判断结束条件
{
if(STAR&0x20)//判断是否抢答按键按下
{
Confirmval = ConfirmVal();
if((STAR&0x1F)==20){Hdtemp --; STAR&=~0x1F;}
DisBuff[0] = AscTable[Btval];
DisBuff[2] = AscTable[Hdtemp/10];
DisBuff[3] = AscTable[Hdtemp%10];
}
else
{
Btval = BottonVal();
if((STAR&0x1F)==20){Qdtemp --; STAR&=~0x1F;}
if(Btval>=1&&Btval<=8)//按键有效
{
TR0 = 0 ;
LED=~LED;
STAR&=~0x1F;//清零计数位
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
STAR|=0x20;//按键标志位
TR0 = 1;
}
DisBuff[2] = AscTable[Qdtemp/10];
DisBuff[3] = AscTable[Qdtemp%10];
}
//时间显示
if(STAR&0x20)
{
if(Hdtemp >= 10) DisStatueSel(DisBuff,1,K);
else DisStatueSel(DisBuff,0,(STAR&0x1F));
}
else
{
if(Qdtemp >= 10) DisStatueSel(DisBuff,1,K);
else DisStatueSel(DisBuff,0,(STAR&0x1F));
}
}
TR0 = 0 ;
if(STAR&0x20)
{
while(!PlayersScore(Btval,score))//设置选手分数
{
DisBuff[0] = AscTable[Btval];
DisBuff[1] = AscTable[score[Btval-1]/10];
DisBuff[2] = AscTable[score[Btval-1]%10];
DisBuff[3] = AscTable[0];
Seg7Dispaly(DisBuff,4);
}
}
//任务执行完成,清除所有相关设置
STAR=0;//清除标志位
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
ClearSegBuff(DisBuff);
}
}
} |