单片机案例开发——八路抢答器(改动)

//八路抢答器说明:P2.7口为显示个位数码管的位选线;P2.6口为显示十位数码管的位选线	;抢答或倒计时结束后按复位键进行下一次抢答.
#include 
#define uchar unsigned char			//宏定义
#define uint  unsigned int
uchar code table[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};	//共阳数码管段码表
sbit beep = P3^4;					//蜂鸣器控制位
sbit XSBHW = P3^5;					//选手编号位1
sbit XSBHW2 = P3^2;					//选手编号位2
sbit DJSBW = P3^3;					//倒计时百位
sbit DJSSW = P3^6;					//倒计时十位
sbit DJSGW = P3^7;					//倒计时个位
uchar num, t1, shu, shu2, temp, bai, shi, ge;	//声明变量
uint i;
//延时子程序
void delay(uint z)
{
	uint x, y;
	for(x = 0; x < z; x++)
		for(y = 0; y < 123; y++);
}
//初始化子程序
void init()
{
	P0 = 0xff;						//消隐
	P2 = 0xff;
	P1 = 0x0f;						//保证抢答前P1口全为高电平(单片机检测低电平认为抢答)
	P3 = 0xff;
	temp = P1;
	TMOD = 0x01;					//选择定时器0为工作方式
	TH0 = (65536 - 50000) / 256;	//定时器装初值
	TL0 = (65536 - 50000) % 256;
	
	EA = 1;							//开总中断
	ET0 = 1;						//开定时器0
	TR0 = 1;						//启动定时器0
	num = 200;						//倒计时数为200
}

void display()						//抢答倒计时显示子函数
{
    bai = num / 100;
	shi = num / 10 % 10;
	ge = num % 10;
	P0 = table[bai];				//显示bai位,送段码
	XSBHW = 1;
	XSBHW2 = 1;
	DJSBW = 0;						//送位码
	DJSSW = 1;
	DJSGW = 1;
	delay(20);						//延时

	P0 = table[shi];				//显示shi位,送段码
	XSBHW = 1;
	XSBHW2 = 1;
	DJSBW = 1;						//送位码
	DJSSW = 0;
	DJSGW = 1;
	delay(20);

	P0 = table[ge];					//显示个位,送段码
	XSBHW = 1;
	XSBHW2 = 1;						//送位码
	DJSBW = 1;
	DJSSW = 1;
	DJSGW = 0;
	delay(20);						//延时
	XSBHW = 1;
	XSBHW2 = 1;						//送位码
	DJSBW = 1;
	DJSSW = 1;
	DJSGW = 1;
}

//主程序
void main()
{
	init();							//调初始化
	//大循环
	while(1)
	{
		//倒计时显示程序
		P1 = 0x0f;
		while(temp == 0x0f)
		{
			display();				//抢答倒计时显示函数
	        temp = P1;				//判断之前,先把P1口的数据送给temp;
			while(temp != 0x0f)		//判断
		   		break;
		}
		//独立键盘扫描程序
		while(temp != 0x0f)			//有键按下
		{
			delay(5);				//软件延时消抖
			temp = P1;				//重读按键
			while(temp != 0x0f)		//再次确认有键按下
			{
				P1 = 0xef;
				temp = P1;
				temp = temp & 0x0f;
				if(temp != 0x0f)
				{
					switch(temp)		//判断哪个键按下
					{
						case 0x0e : shu = 0 ,shu2 = 1;	//1号选手抢答成功
							P3 = 0xfe;
						    break;
						case 0x0d : shu = 0 ,shu2 = 2;	//2号选手抢答成功
							P3 = 0xfd;
						    break;
						case 0x0b : shu = 0 ,shu2 = 3;	//3号选手抢答成功
							P3 = 0xfb;
						    break;
						case 0x07 : shu = 0 ,shu2 = 4;	//4号选手抢答成功
							P3 = 0xf7;
						    break;
					}
				}
				else 
				{
					P1 = 0xdf;
					temp = P1;
					temp = temp & 0x0f;
					if(temp != 0x0f)
					{
						switch(temp)		//判断哪个键按下
						{
							case 0x0e : shu = 0 ,shu2 = 5;	//5号选手抢答成功
								P3 = 0xef;
							    break;
							case 0x0d : shu = 0 ,shu2 = 6;	//6号选手抢答成功
								P3 = 0xdf;
							    break;
							case 0x0b : shu = 0 ,shu2 = 7;	//7号选手抢答成功
								P3 = 0xbf;
							    break;
							case 0x07 : shu = 0 ,shu2 = 8;	//8号选手抢答成功
								P3 = 0x7f;
							    break;
						}
					}
					else
					{
					    P1 = 0xbf;
					temp = P1;
					temp = temp & 0x0f;
					if(temp != 0x0f)
					{
						switch(temp)		//判断哪个键按下
						{
							case 0x0e : shu = 0 ,shu2 = 9;	//9号选手抢答成功
								P3 = 0xef;
							    break;
							case 0x0d : shu = 1 ,shu2 = 0;	//10号选手抢答成功
								P3 = 0xdf;
							    break;
							case 0x0b : shu = 1 , shu2 = 1;	//11号选手抢答成功
								P3 = 0xbf;
							    break;
							case 0x07 : shu = 1 , shu2 = 2;	//12号选手抢答成功
								P3 = 0x7f;
							    break;
						}
					}
					else
					{ 
					   P1 = 0x7f;
				   	   temp = P1;
					   temp = temp & 0x0f;
					   if(temp != 0x0f)
					   {
						  switch(temp)		//判断哪个键按下
						  {
							case 0x0e : shu = 1 ,shu2 = 3;	//13号选手抢答成功
								P3 = 0xef;
							    break;
							case 0x0d : shu = 1 ,shu2 = 4;	//14号选手抢答成功
								P3 = 0xdf;
							    break;
							case 0x0b : shu = 1 ,shu2 = 5;	//15号选手抢答成功
								P3 = 0xbf;
							    break;
							case 0x07 : shu = 1 ,shu2 = 6;	//16号选手抢答成功
								P3 = 0x7f;
							    break;
						  }
					   }
				     }
			      }
				}

				P0 = table[shu];			//显示所按下的键,送段码								
				XSBHW = 0;					//送位码
				XSBHW2 = 1;
				DJSBW = 1;
				DJSSW = 1;
				DJSGW = 1;
				delay(20);

				P0 = table[shu2];
				XSBHW = 1;
				XSBHW2 = 0;
				DJSBW = 1;
				DJSSW = 1;
				DJSGW = 1;
				beep = 0;					//开蜂鸣器
				delay(500);					//有键按下时蜂鸣器响500ms
				beep = 1;					//关闭蜂鸣器
				while(1)					//进入死循环,将所按下的键显示并定格,防止有键再按下时将其覆盖;
				{
					EA = 0;
					P0 = table[shu];			//显示所按下的键,送段码					
					XSBHW = 0;					//送位码
			   	    XSBHW2 = 1;
				    DJSBW = 1;
				    DJSSW = 1;
				    DJSGW = 1;
					delay(20);						//延时
					P0 = table[shu2];
					XSBHW = 1;
				    XSBHW2 = 0;
				    DJSBW = 1;
				    DJSSW = 1;
				    DJSGW = 1;
					delay(20);
					display();				//抢答倒计时显示函数
				}
			}
		}
	 }
}	
//定时器T0中断子函数
void timer0() interrupt 1
{
	TH0 = (65536 - 20000) / 256;	//重赋初值,定时时间为20ms
	TL0 = (65536 - 20000) % 256;
	t1++;
	if(t1 == 50)					//20ms*50=1s,1秒到
	{
		t1 = 0;						//定时计数清0
		num--;						//30秒倒计时
		if(num == 0)
		{ 			
			TR0 = 0;				//关断定时器0
			beep = 0;				//开蜂鸣器
			while(1)				//进入死循环防止超时抢答
			{
				for(i = 0; i < 600; i++)//循环调用显示延时,同时刷新显示
				{
					display();		//抢答倒计时显示函数
				}
				beep = 1;			//关断蜂鸣器 
			}
		}
	}
}

你可能感兴趣的:(单片机案例开发——八路抢答器(改动))