51单片机8路抢答器c语言,51单片机8路抢答器

void Setsecond();//抢答器答题和抢答时间的设置函数声明

void delay(int k); //延时函数声明

//数码管选管位

sbit Sel1=P2^0;

sbit Sel2=P2^1;

sbit Sel3=P2^2;

sbit Sel4=P2^3;

sbit Sel5=P2^4;

sbit Sel6=P2^5;

//抢答器的状态指示灯

sbit led=P2^6;   //显示复位和设置时间的状态

sbit Led1=P3^1;  //抢答失败时,该灯会一直闪烁

sbit Led2=P3^2;  //答题完毕时,该灯会一直闪烁

//抢答器初始化抢答和答题时间按键

sbit Set1=P3^3;  //设置抢答时间,+

sbit Set2=P3^4;  //设置抢答时间,-

sbit Set3=P3^5;  //设置答题时间,+

sbit Set4=P3^6;  //设置答题时间,-

sbit RST=P2^7;   //抢答器的复位按键

sbit EN=P3^0;    //抢答器使能和设置抢答和答题时间按键

unsigned char Tshu1=11,Tshu2=31,shu1=11,shu2=31,shu;//抢答器抢答时间和答题时间的相关变量

unsigned char count0=0,count1=0,roberflag=0,scond1=0,second2=0,robernum=0;//抢答者的相关变量

unsigned char Shuma[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管段码值

bit Enflag=0; //抢答器使能的工作标志变量,0表示正常工作,1表示设置时间(抢答和答题)

void main()  //主函数

{

unsigned char n=0;

TMOD=0x11;Led1=0;Led2=0;

TH0=(2^16-50000)/2^8;TL0=(2^16-50000)%2^8;

TH1=(2^16-50000)/2^8;TL1=(2^16-50000)%2^8;

TR0=1;ET0=1;TR1=1;ET1=1;EA=1;

while(1)

{

for(n=0;n<6;n++) //这个循环,实现数码管的动态显示

{

switch(n)

{

case 0:Sel1=1,Sel2=0,Sel3=0,Sel4=0,Sel5=0,Sel6=0;

if(Enflag == 0)

P0=~Shuma[shu/10];

else

P0=~Shuma[shu1/10];break;

case 1:Sel1=0,Sel2=1,Sel3=0,Sel4=0,Sel5=0,Sel6=0;

if(Enflag == 0)

P0=~Shuma[shu%10];

else

P0=~Shuma[shu1%10];break;

case 2:Sel1=0,Sel2=0,Sel3=1,Sel4=0,Sel5=0,Sel6=0;P0=0xBF;break;

case 3:Sel1=0,Sel2=0,Sel3=0,Sel4=1,Sel5=0,Sel6=0;P0=0xBF;break;

case 4:Sel1=0,Sel2=0,Sel3=0,Sel4=0,Sel5=1,Sel6=0;

if(Enflag == 0)

P0=~Shuma[robernum/10];

else

P0=~Shuma[shu2/10];break;

case 5:Sel1=0,Sel2=0,Sel3=0,Sel4=0,Sel5=0,Sel6=1;

if(Enflag == 0)

P0=~Shuma[robernum%10];

else

P0=~Shuma[shu2%10];break;

}

delay(20);

P0=0xff;

}

}

}

void delay(int k)   //延时函数,主要是为了数码管的动态显示

{

while(k--);

}

void Timer0() interrupt 1  //定时器0,主要用于各种按键的扫描,每200ms一次

{

TH0=(2^16-50000)/2^8;TL0=(2^16-50000)%2^8;

count0++;

P1=0x00;

if(count0 == 5)

{

count0=0;

Setsecond();  //调用设置时间函数,检测是否有设置时间的动作

if(RST == 0) //检测是否有复位动作,有动作,则实现部分变量初始化值

{

roberflag=0;

robernum=0;shu=0;

led=~led;Led1=0;Led2=0;

shu1=Tshu1;shu2=Tshu2;

}

if(EN == 0)

{

Enflag=~Enflag;

led=~led;Led1=0;Led2=0;

}

if(Enflag == 0) //正常工作时候的,抢答人号码的识别和显示(同时判断8口,不准次扫描,无优先级)

{

if(P1 != 0x00)

{

if(roberflag == 0) //只有在抢答时间才能抢答,roberflag=0表示抢答,1答题,2抢答失败,3答题完毕

{

roberflag++;

switch(P1)

{

case 0x01:robernum=1;break;

case 0x02:robernum=2;break;

case 0x04:robernum=3;break;

case 0x08:robernum=4;break;

case 0x10:robernum=5;break;

case 0x20:robernum=6;break;

case 0x40:robernum=7;break;

case 0x80:robernum=8;break;

default:break;

}

}

}

}

}

}

void Timer1() interrupt 3    //定时器1主要是用于工作时的数码显示,跑表,1一秒刷新一次

{

TH1=(2^16-50000)/2^8;TL1=(2^16-50000)%2^8;

if(roberflag == 2)

Led1=~Led1;

if(roberflag == 3)

Led2=~Led2;

count1++;

if(count1 == 20) //正常工作时候的跑表

{

if(Enflag == 0)

{

if(roberflag == 0)  //抢答时间的跑表

{

shu1--;

shu = shu1;

}

if(roberflag == 1)  //答题时间的跑表

{

shu2--;

shu = shu2;

}

if(shu1 == 0)

roberflag=2;

if(shu2 == 0)

roberflag=3;

}

count1=0;

}

}

void Setsecond()   //抢答时间和答题时间设置函数,也是被T0调用,实现设置时间功效。

c2c9ed493cd281aa86d8a6f5178c4c01.gif [1] [2] 610626052e95c7fbe3d254abc769d9ad.gif

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本程序使用51单片机和四个数码管,实现四抢答器功能。 程序思:每个数码管使用一个引脚作为数码管位选(选择哪个数码管显示),其他引脚作为段选(显示数字)。每个抢答按键按下时,判断是否已有人按下,若没有,则该按键胜出,该数码管显示对应数字,并将该按键胜出标志置1;若已有人按下,则不操作。当四个按键都被按下后,清除所有按键的胜出标志,等待下一轮抢答。 代码如下: ``` #include <reg51.h> #define uint unsigned int #define uchar unsigned char sbit dig1 = P1^0; // 数码管1的位选引脚 sbit dig2 = P1^1; // 数码管2的位选引脚 sbit dig3 = P1^2; // 数码管3的位选引脚 sbit dig4 = P1^3; // 数码管4的位选引脚 sbit led0 = P2^4; // 抢答器0的LED指示灯 sbit led1 = P2^5; // 抢答器1的LED指示灯 sbit led2 = P2^6; // 抢答器2的LED指示灯 sbit led3 = P2^7; // 抢答器3的LED指示灯 sbit key0 = P3^0; // 抢答器0的按键 sbit key1 = P3^1; // 抢答器1的按键 sbit key2 = P3^2; // 抢答器2的按键 sbit key3 = P3^3; // 抢答器3的按键 uchar code numTable[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; //0~9的数码管段选值 void delay(uint x) //延时函数 { uint i,j; for(i=x;i>0;i--) for(j=110;j>0;j--); } void display(uchar num, uchar dig) //显示指定数字在指定数码管上 { switch(dig) //选择要显示的数码管 { case 1: dig1 = 0; P0 = numTable[num]; delay(1); dig1 = 1; break; case 2: dig2 = 0; P0 = numTable[num]; delay(1); dig2 = 1; break; case 3: dig3 = 0; P0 = numTable[num]; delay(1); dig3 = 1; break; case 4: dig4 = 0; P0 = numTable[num]; delay(1); dig4 = 1; break; } } uchar getWinner(void) //获取获胜的抢答器编号 { if(key0 == 0) //抢答器0按键按下了 { if(led0 == 0) //未有人按下,胜出 { led0 = 1; //指示灯亮 return 0; } } if(key1 == 0) //抢答器1按键按下了 { if(led1 == 0) //未有人按下,胜出 { led1 = 1; //指示灯亮 return 1; } } if(key2 == 0) //抢答器2按键按下了 { if(led2 == 0) //未有人按下,胜出 { led2 = 1; //指示灯亮 return 2; } } if(key3 == 0) //抢答器3按键按下了 { if(led3 == 0) //未有人按下,胜出 { led3 = 1; //指示灯亮 return 3; } } return 0xff; //没有人获胜,返回0xff } void clearWinner(void) //清除所有获胜者 { led0 = 0; led1 = 0; led2 = 0; led3 = 0; } void main(void) { uchar winner = 0xff; //初始化赢家标志 while(1) { clearWinner(); //清除所有获胜者 while(winner == 0xff) //等待有人按下按键 { winner = getWinner(); //获取获胜的抢答器编号 } display(winner, 1); //在第一位数码管上显示获胜抢答器编号 while(key0 == 0 || key1 == 0 || key2 == 0 || key3 == 0); //等待所有按键松开 winner = 0xff; //重置获胜者标志 } } ``` 该程序需要按键按下后松开,才能继续下一轮抢答。如果需要能够连续抢答(不用松开按键),需要增加按键消抖功能。另外,数码管显示的数字范围为0~3,可以根据需要调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值