基于51单片机的五路抢答器Protues仿真设计
目录
一、设计背景
二、实现功能
三、仿真演示
四、源程序(部分)
一、设计背景
近年来随着科技的飞速发展,单片机的应用正在不断的走向深入。本文阐述了基于51单片机的五路抢答器设计。本设计中,51单片机充当了核心控制器的角色,通过IO口与各个功能模块相连接。按键模块负责检测参与者的抢答动作,当有人按下抢答按钮时,会通过IO口电平的变化通知单片机,单片机会记录按键的次序,并通过数码管显示当前的抢答结果。
为了保证抢答过程的准确性和公平性,设计中还需要考虑到以下因素。首先,按键模块需要具备快速响应和高可靠性,以确保抢答者的动作能够被准确地捕捉到。其次,显示屏模块需要能够实时更新抢答结果,并显示相应的信息,比如参与者的编号和抢答时间。最后,在电路连接方面,需要注意各个模块之间的线路布局,以避免信号干扰和电气问题。
软件系统采用C语言编写程序,包括显示程序,定时中断服务,延时程序等,并在KEIL5中调试运行,硬件系统利用PROTEUS8.11强大的功能来实现,简单切易于观察,在仿真中就可以观察到实际的工作状态。
二、实现功能
以51单片机为控制核心,设计一种五路抢答器。整个系统包括MCU、晶振电路、时钟电路、蜂鸣器控制电路、指示灯控制电路、独立按键电路、矩阵键盘以及数码管显示电路等。可具体实现以下功能:
(1)设定矩阵键盘的5个键作为5位选手的抢答按键,键的编号即选手编号,为1~5号,同时设定5个LED灯作为5位选手抢答状态指示;设定1个独立按键作为抢答开始键;选择两位数码管作为倒计时、选手编号及犯规显示;选择蜂鸣器作为开始、抢答、犯规和计时结束的提示。
(2)只有当裁判按下开始键时才可以进入正常抢答,否则属于犯规抢答。抢答完毕,或计时时间到,停止抢答,数码管显示0。当裁判按下抢答开始键时,开始抢答,计时器开始倒计时,10秒倒计期间,若有抢答,则停止计时,相应选手的LED灯亮,数码管显示选手号;若倒计时结束时无人抢答,则停止抢答。
(3)正确抢答时,抢答选手的LED灯缓慢闪烁,数码管显示抢答选手的编号;犯规抢答时,犯规选手的LED灯快速闪烁,低位数码管显示犯规选手的编号,高位数码管显示F(foul,犯规)。
(4)开始抢答按键按下时、倒计时结束时和抢答键按下时蜂鸣器响1声,犯规时响2声。
三、仿真演示
未运行仿真时,数码管不显示。
运行仿真后,进入准备界面,数码管显示00。
按下启动按键,蜂鸣器响一声,进入抢答界面,开始10秒抢答倒计时。
在抢答倒计时范围内,按下序号为1~5的选手抢答按键,蜂鸣器响1声,数码管上显示抢答选手序号,并且相应序号的指示灯缓慢闪烁4次。
当裁判未按下开始键时,若有选手抢答视为犯规抢答,蜂鸣器响2声指示犯规抢答犯规选手的LED灯快速闪烁20次,低位数码管显示犯规选手的编号,高位数码管显示F。
无论是正常抢答还是犯规抢答,指示灯停止闪烁后,数码管显示00,表示一次抢答结束。
按下复位按钮恢复到准备界面,以便进行下一次抢答。
四、源程序(部分)
#include "reg52.h" #include "delay.h" #include "smg.h" #include "timer.h" sbit key1Led = P3^1; //四位选手 sbit key2Led = P3^2; sbit key3Led = P3^3; sbit key4Led = P3^4; sbit key5Led = P3^5; sbit start_stop = P3^6; //抢答按钮 sbit Beep = P3^7; //抢答按钮 _bool action = 0; _bool key1_flag = 0; _bool key2_flag = 0; _bool key3_flag = 0; _bool key4_flag = 0; _bool key5_flag = 0; _bool Rush_flag = 0; _bool reset_flag = 0; //复位标志位 _bool start_stop_flag = 0; //抢答标志位 _bool BeepF=0; uint8 second = 0; //时间 uint8 timer0_count = 0; //定时器1计数值 uint8 LedFre0Count = 0; uint8 LedFre1Count = 0; uint8 number = 0; //队号 uint8 number_display = 0; //队号显示 uint8 a = 0xff; //按键值 uint8 key_scan8(void); uint8 Fval = 0; void start_stop_keyscan(void); void keycheckdown(void); /* 反转法键盘扫描 */ /*----------------------------------------------------------- 主函数 ------------------------------------------------------------*/ void LedDisplay(uint8 _number) { switch(_number) { case 1: key1Led=~key1Led; break; case 2: key2Led=~key2Led; break; case 3: key3Led=~key3Led; break; case 4: key4Led=~key4Led; break; case 5: key5Led=~key5Led; break; } } void SMG_delay(uint8 t) { while(t--) { display(second); } } void SMG_Bdelay(uint8 t) { while(t--) { P2 = 0xfe; P0 = table[number_display]; Delay_ms(2); P2 = 0xfd; P0 = table[15]; Delay_ms(2); } } void keycheckdown() /* 反转法键盘扫描 */ { short temp1,temp2,temp; P1=0xf0; /* 输入行值(或列值) */ SMG_delay(20); temp1=P1; /* 读列值(或行值) */ P1=0xff; SMG_delay(20); P1=0x0f; /* 输入列值(或行值) */ SMG_delay(20); temp2=P1; /* 读行值(或列值) */ P1=0xff; temp=(temp1&0xf0)|(temp2&0xf); /* 将两次读入数据组合 */ switch(temp) /* 通过读入数据组合判断按键位置 */ { case 0x77 :a=0x0a;break;// 按键+ case 0x7b :a=0x0e; break;// 按键= case 0x7d :a=0; break;// 按键0 case 0x7e :a=0x0f; break;// 按键CE case 0xe7 :a=0x0d;break;// 按键/ case 0xeb :a=0x9;break; // 按键9 case 0xed :a=0x8;break; // 按键8 case 0xee :a=0x7;break; // 按键7 case 0xd7 :a=0x0c;break;// 按键* case 0xdb :a=0x6;break; // 按键6 case 0xdd :a=0x5;Beep=0;SMG_delay(500);Beep=1;break; // 按键5 case 0xde :a=0x4;Beep=0;SMG_delay(500);Beep=1;break; // 按键4 case 0xb7 :a=0x0b; break;// 按键- case 0xbb :a=3;Beep=0;SMG_delay(500);Beep=1;break; // 按键3 case 0xbd :a=2;Beep=0;SMG_delay(500);Beep=1;break; // 按键2 case 0xbe :a=1;Beep=0;SMG_delay(500);Beep=1;break; // 按键1 default :a=0xff; } } void main() { ConfigTimer0();//定时器初始化 while(1) { start_stop_keyscan();//开始按键 keycheckdown();//键盘扫描 Fval=key_scan8(); if(action)//有队抢答 { second=10; } else { if(a!=0xff) { Rush_flag=1;//违规抢答 second=8; TR0=1; } } while(Rush_flag==1) { if(BeepF==0) { Beep=0; SMG_Bdelay(200); Beep=1; SMG_Bdelay(200); Beep=0; SMG_Bdelay(200); Beep=1; BeepF=1; } P2 = 0xfe; P0 = table[number_display]; Delay_ms(2); P2 = 0xfd; P0 = table[15]; Delay_ms(2); if(second==0) { Rush_flag=0; TR0=0; key1Led = 1; key2Led = 1; key3Led = 1; key4Led = 1; key5Led = 1; BeepF=0; break; } } while(action==1)//按下开始键为1,抢答结束为0 { while(!key_scan8()) //无队抢答 { display(second); TR0 = 1; if(second == 0) { Beep=0; SMG_delay(200); Beep=1; break; } keycheckdown();//键盘扫描 } if(number_display)//有队抢答 { second=8; } while(number_display) { display(number_display); if(second == 0) { key1Led = 1; key2Led = 1; key3Led = 1; key4Led = 1; key5Led = 1; break; } } TR0 = 0;//时间到 second=0; display(second); action = 0;//抢答结束 break; } display(second); } } /*----------------------------------------------------------- 中断服务函数 ------------------------------------------------------------*/ void timer0() interrupt 1 { TH0 = (65536-50000)/256; //50ms TL0 = (65536-50000)%256; timer0_count ++; if(timer0_count == 20)//1s { timer0_count = 0; second--; //10s倒计时 if(second == 0)//计时结束 { TR0 = 0; number_display = 0; action = 0; second = 0; } } if(number_display!=0) { if(Rush_flag==0) { LedFre0Count++; if(LedFre0Count==20) { LedFre0Count=0; LedDisplay(number_display); } } else { LedFre1Count++; if(LedFre1Count==5) { LedFre1Count=0; LedDisplay(number_display); } } } } /*----------------------------------------------------------- 开始键扫描函数 ------------------------------------------------------------*/ void start_stop_keyscan(void) { if(start_stop == 0) { SMG_delay(800); if((start_stop == 0)&&(!start_stop_flag)) { start_stop_flag = 1; action = 1; TR0 = 1; Beep=0; SMG_delay(200); Beep=1; reset_flag = 0; } } else { start_stop_flag = 0; } } /*----------------------------------------------------------- 四位抢答键扫描函数 ------------------------------------------------------------*/ uint8 key_scan8(void) { if((a == 1)&&(!key1_flag)) { key1_flag = 1; number = 1; number_display = number; } else { key1_flag = 0; number = 0; } if((a == 2)&&(!key2_flag)) { key2_flag = 1; number = 2; number_display = number; } else { key2_flag = 0; number = 0; } if((a == 3)&&(!key3_flag)) { key3_flag = 1; number = 3; number_display = number; } else { key3_flag = 0; number = 0; } if((a == 4)&&(!key4_flag)) { key4_flag = 1; number = 4; number_display = number; } else { key4_flag = 0; number = 0; } if((a == 5)&&(!key5_flag)) { key5_flag = 1; number = 5; number_display = number; } else { key5_flag = 0; number = 0; } if(number_display != 0) { return 1; } else { return 0; } }
仿真源文件及源程序百度网盘链接:https://pan.baidu.com/s/12J02HAeeTJgKW468viFx1g
提取码:kc9n