找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 22168|回复: 38
收起左侧

单片机做的8位抢答器完整原理图及程序

  [复制链接]
ID:50996 发表于 2013-6-17 02:43 | 显示全部楼层 |阅读模式
这儿是10年广西区初赛时大一组的题目。当时大一,写程序经验不够丰富,以致程序的样子写得难看点,但是还是实现了必要的功能。
功能如下:显示抢答、回答时间倒计时,能够调节抢答、回答时间,能够报警犯规抢答,可以计分,可以实现软复位
使用AT89S52 单片机。四位数码管(为啥我没有选择用液晶,因为我觉得液晶做的抢答器根本不具有实用性)。我所认为的实用性是做出来的东西是能够使用的而不是模型。同时我的8个按键都是分开来做的,也是实用性的考虑(附件里有实物图)。

实物图1.jpg
实物图2.jpg

8路抢答器完整原理图及程序.rar (239.51 KB, 下载次数: 438)

评分

参与人数 2黑币 +10 收起 理由
伟云科技 + 5 楼主能把文件发给我一下吗,我刚注册的,无.
kakityuen + 5 很给力!

查看全部评分

回复

使用道具 举报

ID:1 发表于 2013-6-17 03:53 | 显示全部楼层
下面是主程序文件:
/*八路抢答器-----能够显示抢答、回答时间倒计时,能够调节抢答、回答时间,能够报警犯规抢答,可以计分,可以实现软复位*/
/*桂林电子科技大学*信息与通信学院*电子科学与技术*/
/*此程序仅供参考!!恳请自重*/
/*本人博客: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 main()
{
	uchar AnJian,ShuJu,XuanShou_num;
Top:init();//初始化
	XuanShou_num=1;//为分数查询做好准备
	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(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%10];//时间的个位
		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]%10)];//分数的个位
		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;
	 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;
				}
			}
		}
	}
}
回复

使用道具 举报

ID:51014 发表于 2013-6-17 20:03 | 显示全部楼层
有仿真图吗,想试试改改程序
回复

使用道具 举报

ID:50943 发表于 2013-6-22 14:16 | 显示全部楼层
学习来了
回复

使用道具 举报

ID:50943 发表于 2013-6-22 14:21 | 显示全部楼层
兄弟 发我个仿真图  QQ 623205804
回复

使用道具 举报

ID:46866 发表于 2013-10-1 15:48 | 显示全部楼层
回复

使用道具 举报

ID:62288 发表于 2014-5-26 12:39 | 显示全部楼层
好东西的,谢谢。
回复

使用道具 举报

ID:62314 发表于 2014-5-26 22:53 | 显示全部楼层
看一下
回复

使用道具 举报

ID:70484 发表于 2014-12-15 09:03 | 显示全部楼层
看一下
回复

使用道具 举报

ID:70484 发表于 2014-12-15 09:04 | 显示全部楼层
楼主好人
回复

使用道具 举报

ID:70499 发表于 2014-12-18 12:24 | 显示全部楼层
看看,,
回复

使用道具 举报

ID:72881 发表于 2015-1-27 19:26 | 显示全部楼层
很好很强大。
回复

使用道具 举报

ID:78618 发表于 2015-5-7 19:30 | 显示全部楼层
楼主有没有proteus仿真图?毕业设计急需呀。不然就要淘宝了。。。
回复

使用道具 举报

ID:78618 发表于 2015-5-7 19:38 | 显示全部楼层
89c51123 发表于 2015-5-7 19:30
楼主有没有proteus仿真图?毕业设计急需呀。不然就要淘宝了。。。

邮箱:q1063289287@163.com
回复

使用道具 举报

ID:75461 发表于 2015-5-8 16:40 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:77907 发表于 2015-5-9 20:28 | 显示全部楼层
谢谢分享!!!
回复

使用道具 举报

ID:92234 发表于 2015-10-12 15:16 | 显示全部楼层
回一贴
回复

使用道具 举报

ID:69482 发表于 2015-10-13 15:00 | 显示全部楼层
楼主  为什么里面程序没有定义另外八个抢答器的引脚
回复

使用道具 举报

ID:69482 发表于 2015-10-13 15:08 | 显示全部楼层
有 看到了 是P1口
回复

使用道具 举报

ID:69482 发表于 2015-10-13 21:56 | 显示全部楼层
这个作品要如何使用
回复

使用道具 举报

ID:36525 发表于 2015-10-13 22:52 | 显示全部楼层
根本就没有仿真图。浪费5个黑币
回复

使用道具 举报

ID:36525 发表于 2015-10-13 22:53 | 显示全部楼层
那二个文件怎么打开,有什么软件
回复

使用道具 举报

ID:36525 发表于 2015-10-13 22:55 | 显示全部楼层
没仿真图
回复

使用道具 举报

ID:93169 发表于 2015-10-21 21:40 | 显示全部楼层
好东西的,谢谢。
回复

使用道具 举报

ID:97032 发表于 2015-11-24 23:32 | 显示全部楼层
我要我要我要我要我要我要我要我要我要我要我要我要
回复

使用道具 举报

ID:107352 发表于 2016-6-20 11:21 | 显示全部楼层
看着好厉害学习一下
回复

使用道具 举报

ID:157782 发表于 2016-12-26 16:39 | 显示全部楼层
楼主 还有仿真图么】
回复

使用道具 举报

ID:160801 发表于 2017-1-8 17:32 | 显示全部楼层
厉害了
回复

使用道具 举报

ID:195723 发表于 2017-5-2 20:11 | 显示全部楼层
过来学习一下,不知道楼主现在还能不能看到
回复

使用道具 举报

ID:222799 发表于 2017-7-27 23:39 | 显示全部楼层
想请教一下程序中TOP:以及LOSE:这是代表什么
回复

使用道具 举报

ID:130345 发表于 2017-8-4 18:24 | 显示全部楼层
厉害了
回复

使用道具 举报

ID:268011 发表于 2017-12-27 21:07 | 显示全部楼层
怎么获得黑币,我下载不了
回复

使用道具 举报

ID:268991 发表于 2017-12-29 23:12 来自手机 | 显示全部楼层
有图么
回复

使用道具 举报

ID:287570 发表于 2018-3-4 22:17 | 显示全部楼层
厉害呀
回复

使用道具 举报

ID:86974 发表于 2018-5-13 14:00 | 显示全部楼层
可以看看吗?
回复

使用道具 举报

ID:418371 发表于 2018-10-31 10:24 | 显示全部楼层
赞一个
回复

使用道具 举报

ID:418410 发表于 2018-10-31 11:12 | 显示全部楼层
赞一个
回复

使用道具 举报

ID:428733 发表于 2018-11-18 16:10 | 显示全部楼层
谢谢,用处很大
回复

使用道具 举报

ID:335259 发表于 2019-10-19 16:31 | 显示全部楼层
楼主,能不能分享一下Proteus仿真图呀
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表