8路遥控抢答器
源代码在线查看: 抢答器程序.txt
#include
#define LED P2 //宏定义,使用LED代替P3口(相当于LED=P3)
#define uchar unsigned char //用uchar代替unsigned char方便操作
#define uint unsigned int
sbit beep=P2^7;//蜂鸣器
sbit BG=P3^7;//指示灯
sbit key4=P1^0;//按键D
sbit key2=P1^1;//按键B
sbit key1=P1^2;//按键A
sbit key3=P1^3;//按键C
bit time_over=0;//倒计时结束标记
bit WARNING=0;//倒数十秒控制变量
bit INT_ON=0;//中断标记
bit key_down=0;//键盘辅助变量
uchar RIGHT=0xff;//按键暂存器
uchar CONT=0; //定时器辅助变量
uchar res_time=0;//时间
uchar set_time=30;
uchar leds[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
0x90,0x88,0x83,0xa7,0xa1,0x86,0x8e,0xff};
/*------------------time ms延时函数-----------------*/
void delay_ms(uint time)
{
uchar tres;
for(;time>0;time--)
{
tres=150;
while(tres--);
}
}
//外部中断1初始化程序
void Init_Sys() //中断初始化函数
{
TCON=0x00; //外部中断1低电平触发
TMOD=0X01; //定时器0方式1
IE=0x86; //开启外部中断1,定时器中断0,及总中断 10000110B
IP=0X04; //外部中断优先级高于定时器
CONT=0; //时间清零
res_time=0;
}
//外部中断1处理程序
void exint1_int() interrupt 2 using 0
{
uchar t=200;
EA=0;//关中断
TR0=0;//关定时器
WARNING=0;//关警告
while(t--)beep=0;//软件延时,消除抖动
RIGHT=P0; //获得按键值
INT_ON=1; //标记中断
}
//定时器0中断处理程序
void count_int() interrupt 1 using 1
{
TH0=0X4C;//重新装载
TL0=0X00;
CONT++;
if(CONT==20)
{
CONT=0;
if(res_time==0)time_over=1;
res_time--;
}
}
//遥控按键扫描程序
uchar key_scan(void)
{
P1=0xff;
if(key1==1||key2==1||key3==1||key4==1)
{
if(!key_down)
{
delay_ms(10); //延时
key_down=1; //限制
if(key1==1)return 1;//按键A
if(key2==1)return 2;//按键B
if(key3==1)return 3;//按键C
if(key4==1)return 4;//按键D
}
else return 0;
}
else if(key_down)key_down=0;//消除限制
return 0; //未获得任何按键
}
uchar juder(void)
{
switch(RIGHT)
{
case 0xff:return 0;
case 0xfe:return 1;
case 0xfd:return 2;
case 0xfb:return 3;
case 0xf7:return 4;
case 0xef:return 5;
case 0xdf:return 6;
case 0xbf:return 7;
case 0x7f:return 8;
default:return 14;//E,错误
}
}
//显示答案
void show_answer(void)
{
uchar ti=0;
uchar key=0;
while(1)
{
key=key_scan();
if(ti==100){BG=!BG;ti=0;}
if(key!=0)
{
LED=leds[key+9];//显示答案
BG=1;//灭灯
break;
}
ti++;
delay_ms(1);
}
}
void BELL(uchar times)
{
while(times--)
{
beep=0;
delay_ms(100);
beep=1;
delay_ms(100);
}
}
//清除显示
void clear(void)
{
EA=0; //关掉计时器
beep=0; //开蜂鸣器
WARNING=0; //清警告标记
time_over=0;//清溢出标记
TR0=0; //关定时器
INT_ON=0;//清除中断标记
TL0=0X00;//初始值设置
TH0=0X4C;
CONT=0;
res_time=set_time;//赋初始值
delay_ms(100);
LED=leds[16];//清屏,同时关蜂鸣器
BG=1;//关灯
}
void debug(void)//处理犯规队,显示犯规队队号
{
RIGHT=P0;//获得犯规队的地址
LED=leds[juder()];//显示队号
BELL(4);
}
//开启抢答器
//1普通模式
//0倒计时模式
void start(uchar type)
{
bit alarm=1;//提示音
uchar key=0;
res_time=set_time;//获取初始值
while(1)
{
key=key_scan();//扫描键盘
if(key!=0)
{
switch(key)
{
case 1://显示答案
{
clear();//清除
show_answer();
break;
}
case 2://开始抢答
{
if(P0!=0XFF)
{
debug();//处理犯规
break;
}
if(!type)TR0=1; //倒计时方式
else //普通方式
{
clear();
BG=0;//开灯指示
}
EA=1;//使能中断
break;
}
case 3:clear();break;//清除
case 4:return;//返回
}
}
if(TR0==1)//倒计时
{
if(CONT==0&&BG)
{
if(res_time>=10)LED=leds[res_time/10];
BG=0;//每秒钟闪烁一次
if(WARNING)alarm=0;//最后十秒
}
if(CONT==10&&!BG)
{
BG=1;
if(WARNING)alarm=1;//最后十秒
else LED=leds[res_time%10];//显示个位数据;
}
if(res_time {
WARNING=1;
LED=leds[res_time];
}
beep=alarm;
delay_ms(5);
}
if(time_over) //倒计时结束处理
{
clear();
LED=leds[0];
time_over=0;
BELL(3);
}
if(INT_ON)//有选手按下
{
TR0=0;//关定时器
beep=0;//开提示音
BG=1;//关灯
delay_ms(100);
INT_ON=0;
LED=leds[juder()];//显示选手号
}
}
}
void main()
{
bit set=0;//设置状态标记
bit model=1; //模式标记
uchar key;
Init_Sys();//初始化外部中断 1 捕获按键输入
P0=0XFF;
TR0=1;//开启定时器0
while(1)//死循环
{
key=key_scan();
if(key!=0)
{
if(!model)switch(key)
{
case 1:
{
set=1;
set_time+=10;
if(set_time>90)set_time=10;
break;
}
case 3:
{
set=1;
if(set_time>10)set_time-=10;//范围限制
else set_time=90;
break;
}
}
if(key==2)
{
start(model);//开始抢答
set=0;//非设置状态
}
if(key==4)
{
model=!model;//模式切换
set=0; //非设置状态
}
}
if(model)LED=leds[14];
else
{
if(set)LED=leds[set_time/10];//显示设置时间
else LED=leds[15];
}
}
}