单片机8路抢答器
文件大小: 47k
源码售价: 10 个金币 积分规则     积分充值
资源说明:单片机8路抢答器 代码仿真/*八路抢答器-----能够显示抢答、回答时间倒计时,能够调节抢答、回答时间,能够报警犯规抢答,可以计分,可以实现软复位*/ /*桂林电子科技大学*信息与通信学院*电子科学与技术*/ /*此程序仅供参考!!恳请自重*/ /*本人博客:http://blog.sina.com.cn/13302xiaoqiao */ /*欢迎交流*/ #include #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];//时间的个位 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(uchar char_1,uchar char_2,uchar char_3,uchar char_4 )//闪动!显示字符的函数 { shan_count++; if(shan_count==150) shan_count=0; if(shan_count>0&&shan_count<50) { P2=0x7f;//0111 1111 P0=table_char[char_4]; delay(1); P2=0x7f;//0111 1111 P0=0xff; delay(1); P2=0xbf;//1011 1111 P0=table_char[char_3]; delay(1); P2=0xbf;//1011 1111 P0=0xff; delay(1); P2=0xdf;//1101 1111 P0=table_char[char_2]; delay(1); P2=0xdf;//1101 1111 P0=0xff; delay(1); P2=0xef;//1110 1111 P0=table_char[char_1]; delay(1); P2=0xef;//1110 1111 P0=0xff; delay(1); } else { P2=0x7f;//0111 1111 P0=0xff; delay(1); P2=0xbf;// P0=0xff; delay(1); P2=0xdf;// P0=0xff; delay(1); P2=0xef;// P0=0xff; delay(1); } } void display_set(uchar char_1,uchar time,uchar char_2)//时间设置的闪动显示 { shan_count++; if(shan_count==120) shan_count=0; if(shan_count>0&&shan_count<40) { P2=0x7f;//0111 1111最后一位数码管亮 P0=table[char_2];//显示一个符号 delay(1); P2=0x7f;//0111 1111 P0=0xff;//消余辉 delay(1); P2=0xbf;//1011 1111 P0=table[time];//时间的个位 delay(1); P2=0xbf;//1011 1111 P0=0xff;//消余辉 delay(1); P2=0xdf;//1101 1111 P0=table[time/10];//时间的十位 delay(1); P2=0xdf;//1101 1111 P0=0xff;//消余辉 delay(1); P2=0xef;// 1110 1111 P0=table[char_1];//显示一个符号 delay(1); P2=0xef;//1110 1111 P0=0xff;//消余辉 delay(1); } else { P2=0x7f;//0111 1111 P0=table[char_2]; delay(1); P2=0xbf;// P0=0xff; delay(1); P2=0xdf;// P0=0xff; delay(1); P2=0xef;// P0=table[char_1]; delay(1); } } void display_score(uchar xs_num)//分数查询显示函数 { P2=0x7f;//0111 1111最后一位数码管亮 P0=table[(table_score[xs_num])];//分数的个位 delay(1); P2=0x7f;//0111 1111 P0=0xff;//消余辉 delay(1); P2=0xbf;//1011 1111 P0=table[(table_score[xs_num]/10)];//分数的十位 delay(1); P2=0xbf;//1011 1111 P0=0xff;//消余辉 delay(1); P2=0xdf;//1101 1111 P0=table_char[15];//间隔符号 delay(1); P2=0xdf;//1101 1111 P0=0xff;//消余辉 delay(1); P2=0xef;// 1110 1111 P0=table[xs_num];//选手编号 delay(1); P2=0xef;//1110 1111 P0=0xff;//消余辉 delay(1); } void beep() //有源蜂鸣器函数 { // fmq=0; beep_x(); // delay(80); //fmq=1; } void beep_last()//最后一声特殊声调 { fmq=0; delay(300); fmq=1; } void LED() { led=0; delay(150); led=1; } void T0_time() interrupt 1//定时器0中断函数_回答时间 { TH0=(65536-50000)/256;//50ms TL0=(65536-50000)%256;//马上重装初值,以免有误差 if(count_0==20) { count_0=0; HuiDa_time--; if(HuiDa_time<=5) { if(HuiDa_time==0) { beep_last();//最后一声特殊警告 } beep(); } } count_0++; } void T1_time() interrupt 3//定时器1中断函数_抢答时间 { TH1=(65536-50000)/256;//50us TL1=(65536-50000)%256;//马上重装初值,这样在后面调用beep()函数时就不会影响定时器的准确计时了 if(count_1==20) { count_1=0; QiangDa_time--; if(QiangDa_time<=5) { if(QiangDa_time==0) { beep_last();//最后一声警告 } else beep(); } } count_1++; } void EX0_set_QiangDa_time() interrupt 0 //外中断0,设置抢答时间 { delay(10);//消抖一下 if(Key_set_Q==0) { beep(); while(1) { // display(11,QiangDa_time_temp); // delay(100);//闪动效果 display_set(12,QiangDa_time_temp,13);//调用时间设置闪动显示函数,效果为 [时间] if(Key_Start==0)//时间+1键 { delay(10); if(Key_Start==0) { QiangDa_time_temp++; if(QiangDa_time_temp==100) { QiangDa_time_temp=1; } } } while(!Key_Start);//等待按键释放 // else if(Key_Stop==0)//时间-1键 { delay(10); if(Key_Stop==0) { QiangDa_time_temp--; if(QiangDa_time_temp==0) { QiangDa_time_temp=99; } } } while(!Key_Stop);//等待按键释放 // else if(Key_Restart==0) { if(Key_Restart==0) { beep(); break; } } } } } void EX1_set_HuiDa_time() interrupt 2 //外中断1,设置回答时间 { delay(10);//消抖一下 if(Key_set_H==0) { beep(); while(1) { display_set(12,HuiDa_time_temp,13);//调用时间设置闪动显示函数,效果为 [时间] if(Key_Start==0)//时间+1键 { delay(10); if(Key_Start==0) { HuiDa_time_temp++; if(HuiDa_time_temp==100) { HuiDa_time_temp=1; } } } while(!Key_Start);//等待按键释放 // else if(Key_Stop==0)//时间-1键 { delay(10); if(Key_Stop==0) { HuiDa_time_temp--; if(HuiDa_time_temp==0) { HuiDa_time_temp=99; } } } while(!Key_Stop);//等待按键释放 // else if(Key_Restart==0) { if(Key_Restart==0) { beep(); break; } } } } }
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。