一、任务说明
(一)系统总体方案设计与实现
1、系统总体方案设计
本系统由硬件系统和软件系统组成。
硬件系统包括按键控制模块、中央处理AT89C51系统、指示灯显示模块、LED数码管显示模块和扬声器提示模块。
软件系统包括主程序、定时器0中断服务程序、定时器1中断服务程序、延时程序、按键程序和显示程序。
为方便理解,系统框图如下图所示:
图1 系统框图
2、系统总体方案实现
本次单片机课程设计选题是《八路抢答器》。本次课程设计是以八位选手抢答和主持人的控制为出发点。
①只有一个最先抢答有效,其余抢答无效。
②在主持人的控制下,10秒内抢答有效,用数码管显示抢答10秒倒计时,若有抢答直接结束,显示哪个编号抢到,并进入10秒的答题时间。
③若有提前抢答,则犯规,用蜂鸣器响1秒警示。
④有复位按键,用于复位作用,开始新的一轮。
⑤可以设置抢答时间和答题时间,可调范围是0到99秒,超出或低出范围会返回第10秒。
⑥LED警示灯、LED显示屏和蜂鸣器进行倒计时警示,三重的警示,带来极致的紧迫感。
⑦答题时间暂停,可以确定选手最后的答案耗时多长时间,促进选手的公平。
⑧如果选手在规定时间内或违规抢到第一位,不仅屏幕会显示号码,而且对应选手的LED灯会亮起。
(二)硬件电路设计
1、硬件电路图:
①时钟电路模块:
图2 时钟电路
②复位电路模块:
图3 复位电路
③LED显示屏模块:
图4 LED显示屏
④选手抢答按键模块:
图5 选手抢答按键
⑤选手点灯模块:
图6 选手点灯
⑥蜂鸣器提示模块:
图7 蜂鸣器提示
⑦LED灯倒计时警示模块:
图8 LED灯倒计时警示
⑧主持人控制按键模块:
图9 主持人控制按键
2、硬件说明:
本次硬件设计简单来说由:AT89C51最小系统、显示模块、按键模块LED灯和蜂鸣器模块组成。
(三)软件设计
当接通电源开始工作后,单片机中的程序开始运行,将对程序进行初始化。完成初始化后,将进行键盘扫描,同时判断开始按键、调节按键是否按下。最后完成倒计时和选手号码的显示等功能。
软件流程图如下图所示:
图10 软件流程图
二、电路原理图与结果
1、选手违规抢答:以第1位选手违规抢答为例,对应选手的LED灯亮起,LED显示屏显示对应违规选手号码,蜂鸣器先响起1秒警示,如果未进行复位操作,则蜂鸣器将再会响起,同时倒计时警示LED灯会闪烁提示。(第1-8位选手都是如此)
2、抢答时间调整:如果按下抢答时间加键或抢答时间减键,LED显示屏显示对应的调整时间,时间调整范围为0-99秒,超过99秒或低出0秒则返回去10秒。本次将抢答时间增加到15秒。
3、答题时间调整:如果按下答题时间加键或答题时间减键,LED显示屏显示对应的调整时间,时间调整范围为0-99秒,超过99秒或低出0秒则返回去10秒。本次将答题时间减少到8秒。
4、主持人按下开始键:抢答时间开始倒计时,最后几秒抢答时间倒计时警示LED灯将闪烁,要是选手没有选择抢答,则蜂鸣器会不断响起,LED显示屏熄屏,除非按下复位键开启新的一轮。
5、主持人按下开始键:抢答时间开始倒计时,最后几秒抢答时间倒计时警示LED灯将闪烁,要是选手选择抢答,则对应选手的LED灯会亮起。
6、要是选手在抢答时间按下抢答键,进入答题时间:答题时间最后几秒倒计时LED灯亮起,蜂鸣器不断响起,提示按下复位键,开始新的一轮。
6、要是选手在抢答时间按下抢答键,进入答题时间:答题时间内主持人可以按下答题时间暂停键,则显示屏时间暂停,按下答题时间暂停键的第一瞬间LED显示屏熄屏,倒计时LED警示灯亮起,松下答题时间暂停键的第一瞬间LED显示屏显示暂停的时间,倒计时LED警示灯熄灭,除非按下复位键,开始新的一轮。
三、代码说明
代码部分主要由四个模块组成,分别为主程序、显示子程序、时间按键调整子程序、选手按键子程序、开始键子程序、延迟子程序、定时器T0初始化子程序和蜂鸣器和LED灯子程序。
1、主程序:
主程序完成定时器0的初始化、74LS138芯片的初始化和扫描主持人按键,进行对应的操作。
2、显示子程序:
此函数大方向分为开始键按下和开始键没有按下的两种情况。同时两个大方向又各自细分两个小方向。当开始键按下,则有选手在抢答时间按下显示选手号码在LED显示屏上,要是没有则不显示号码。同时显示屏上显示抢答和答题的倒计时。当开始键没有按下,如果有人违规抢答,则显示屏显示违规号码。如果按下答题时间或抢答时间调整键,则对应显示屏进行更新数据操作。
3、时间按键调整子程序:
此函数很简单,要是按下抢答时间或答题时间调整键,则对应时间将进行操作,调整范围为0-99秒,超出99秒或低于0秒,则返回到10秒。
4、选手按键子程序:
以K1为例,程序一直判断按键引脚电压,按下按键电压为0。按键会产生抖动,需要进行消抖处理,先进行消抖延迟10ms,如果按键电压还是0,确定没问题K1进行操作,令按键数目num为1,供主函数处理按键消息。同时将74LS138的对应输入口赋值,数码管显示工作,定时器1和0也进行对应工作。K1-K8功能都是一样的操作。
5、开始键子程序:
如果按下开始键,程序一直判断按键引脚电压,按下按键电压为0。按键会产生抖动,需要进行消抖处理,先进行消抖延迟10ms,如果按键电压还是0,确定没问题K0进行操作.将对应的标志位进行开始工作,将清除违规标志位、开始抢答时间调整键标志位和答题计时时间调整键标志位停止运行。
6、延迟子程序:
确定51单片机为12MHz频率,以此确定ms的延迟子函数。
7、定时器T0初始化子程序:
将定时器T0进行初始化,运用方式1,即16位计数器。取高八位和第八位寄存器进行定时操作。
8、蜂鸣器和LED灯子程序:文章来源:https://www.toymoban.com/news/detail-756889.html
用定时器0和定时器1确定蜂鸣器响多久和LED灯亮。文章来源地址https://www.toymoban.com/news/detail-756889.html
四、源代码
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
char s;
uchar num=0;//谁抢到的号码,初始化为0
char snaptime=10;//抢答时间
char answertime=10;//答题时间
uint t0,t1; //T0,T1定时器
bit flag,s_flag=1,b_flag,fall_flag;//标志位
bit K_snaptimeflag,K_answertimeflag;//时间调整标志位
sbit K0=P3^0;
sbit beep=P3^7;//蜂鸣器输出口
sbit led=P2^4;//指示灯输出口
sbit K1=P1^0;
sbit K2=P1^1;
sbit K3=P1^2;
sbit K4=P1^3;
sbit K5=P1^4;
sbit K6=P1^5;
sbit K7=P1^6;
sbit K8=P1^7;
sbit K_Time=P2^5;//答题暂停键
sbit K_startcount=P2^6;//开始抢答时间+调整键
sbit K_timecount=P3^4;//答题计时时间+调整键
sbit K_startcount0=P2^7;//开始抢答时间-调整键
sbit K_timecount0=P3^5;//答题计时时间-调整键
sbit G=P3^1;
sbit H=P3^2;
sbit I=P3^3;
sbit J=P3^6;
uchar code tabledu[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar code tablewe[]={0XFE,0XFD,0XFB,0XF7};
void delay(uint n)//延时n毫秒
{
uint i=0,j=0;
for(i=0;i<n;i++)
for(j=0;j<123;j++);
}
void T0_Init(void)//定时器T0初始化
{
TMOD=0X01;//使用定时器T0的模式1
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;
ET0=1;
ET1=1;
EA=1;
P0=0;
}
void Start_Scan(void) //开始键扫描
{
if(K0==0)
{
delay(10);
if(K0==0)
{
while(!K0);
TR0=1;//启动定时器0工作
s=snaptime;
t0=0;
flag=1;
s_flag=1;
b_flag=1;
num=0;
beep=1;
led=1;
fall_flag=0;//清除违规标志位
K_snaptimeflag=0;//开始抢答时间调整键停止运行
K_answertimeflag=0;//答题计时时间调整键停止运行
}
}
}
void Select_Scan(void)//八路选择键扫描(哪个键先按下,哪个优先级最高)
{
if(K1==0)
{
delay(10);
if(K1==0)
{
while(!K1);
{
G=0;
H=0;
I=0;
J=1;
num=1;//数码管显示第1位
TR0=0;//关闭定时器0工作,时间停止
TR1=1;//打开定时器1工作 。使扬声器响一声
s_flag=0;//关闭开始键标志位,使再按其他七个键不会响应
delay(10);
}
while(!K_Time);
{
s=answertime;
TR0=1;
t0=0;
TR1=1;
}
}
}
if(K2==0)
{
delay(10);
if(K2==0)
{
while(!K2);
{
G=1;
H=0;
I=0;
J=1;
num=2;
TR0=0;
TR1=1;
s_flag=0;
delay(10);
}
while(!K_Time);
{
s=answertime;
TR0=1;
t0=0;
TR1=1;
}
}
}
if(K3==0)
{
delay(10);
if(K3==0)
{
while(!K3);
{
G=0;
H=1;
I=0;
J=1;
num=3;
TR0=0;
TR0=0;
TR1=1;
s_flag=0;
delay(10);
}
while(!K_Time);
{
s=answertime;
TR0=1;
t0=0;
TR1=1;
}
}
}
if(K4==0)
{
delay(10);
if(K4==0)
{
while(!K4);
{
G=1;
H=1;
I=0;
J=1;
num=4;
TR0=0;
TR1=1;
s_flag=0;
delay(10);
}
while(!K_Time);
{
s=answertime;
TR0=1;
t0=0;
TR1=1;}
}
}
if(K5==0)
{
delay(10);
if(K5==0)
{
while(!K5);
{
G=0;
H=0;
I=1;
J=1;
num=5;
TR0=0;
TR1=1;
s_flag=0;
delay(10);
}
while(!K_Time);
{
s=answertime;
TR0=1;
t0=0;
TR1=1;
}
}
}
if(K6==0)
{
delay(10);
if(K6==0)
{
while(!K6);
{
G=1;
H=0;
I=1;
J=1;
num=6;
TR0=0;
TR1=1;
s_flag=0;
delay(10);
}
while(!K_Time);
{
s=answertime;
TR0=1;
t0=0;
TR1=1;
}
}
}
if(K7==0)
{
delay(10);
if(K7==0)
{
while(!K7);
{
G=0;
H=1;
I=1;
J=1;
num=7;
TR0=0;
TR1=1;
s_flag=0;
delay(10);
}
while(!K_Time);
{
s=answertime;
TR0=1;
t0=0;
TR1=1;}
}
}
if(K8==0)
{
delay(10);
if(K8==0)
{
while(!K8);
{
G=1;
H=1;
I=1;
J=1;
num=8;
TR0=0;
TR1=1;
s_flag=0;
delay(10);
}
while(!K_Time);
{
s=answertime;
TR0=1;
t0=0;
TR1=1;
}
}
}
}
void display(void)
{
if(flag==1)//开始键按下,开始计时抢答
{
if(num!=0)//如果有人抢答,则显示相应的号码
{
P0=tabledu[num];//显示几号抢到了
P2=tablewe[0];
delay(2);
P0=0;
P2=0XFF;
}
else//否则没人抢答,则前面不显示几号
{
P0=0;
P2=0XFF;
}
P0=tabledu[s/10];//显示抢答倒计时的十位
P2=tablewe[2];
delay(2);
P0=0;
P2=0XFF;
P0=tabledu[s%10];//显示抢答倒计时的个位
P2=tablewe[3];
delay(2);
P2=0XFF;
P0=0;
}
if(flag==0)//如果开始键没有按下,若有违规者,则显示违规号码
{
if(fall_flag==1)//违规违规
{
if(num!=0)
{
P0=tabledu[num];//显几号违规了
P2=tablewe[0];
delay(2);
P0=0;
P2=0XFF;
P0=tabledu[15];
P2=tablewe[2];
delay(2);
P0=0;//消隐
P2=0XFF;
P0=tabledu[15];
P2=tablewe[3];
delay(2);
P0=0;
P2=0XFF;
}
else
{
P0=0;
P2=0XFF;
}
}
else
{
if(K_snaptimeflag==1)
{
P0=0XF9;//第1位数码管(表示抢答时间调整)
P2=tablewe[0];
delay(2);
P0=0;
P2=0XFF;
P0=tabledu[snaptime/10];//第x位数码管(表示抢答时间调整)
P2=tablewe[2];
delay(2);
P0=0;
P2=0XFF;
P0=tabledu[snaptime%10];
P2=tablewe[3];
delay(2);
P0=0;
P2=0XFF;
}
else if(K_answertimeflag==1)
{
P0=0X07;//第x位数码管(表示答题时间调整)
P2=tablewe[0];
delay(2);
P0=0;
P2=0XFF;
P0=0X31;
P2=tablewe[1];
delay(2);
P0=0;
P2=0XFF;
P0=tabledu[answertime/10];
P2=tablewe[2];
delay(2);
P0=0;
P2=0XFF;
P0=tabledu[answertime%10];
P2=tablewe[3];
delay(2);
P0=0;
P2=0XFF;
}
}
}
}
void Time_Scan(void)//调整时间键扫描
{
if(K_startcount==0)//抢答时间调整
{
delay(10);
if(K_startcount==0)
{
while(!K_startcount);
snaptime++;
if(snaptime==99||snaptime==0)
{
snaptime=10;
}
K_snaptimeflag=1; //将抢答时间标志位置1
K_answertimeflag=0; //同时关闭答题时间标志位
}
}
if(K_timecount==0) //答题时间调整
{
delay(10);
if(K_timecount==0)
{
while(!K_timecount);
answertime++;
if(answertime==99||answertime==0)
{
answertime=10;
}
K_answertimeflag=1;
K_snaptimeflag=0;
}
}
if(K_startcount0==0)//抢答时间调整
{
delay(10);
if(K_startcount0==0)
{
while(!K_startcount0);
snaptime--;
if(snaptime==99||snaptime==0)
{
snaptime=10;
}
K_snaptimeflag=1; //将抢答时间标志位置1
K_answertimeflag=0; //同时关闭答题时间标志位
}
}
if(K_timecount0==0) //答题时间调整
{
delay(10);
if(K_timecount0==0)
{
while(!K_timecount0);
answertime--;
if(answertime==99||answertime==0)
{
answertime=10;
}
K_answertimeflag=1;
K_snaptimeflag=0;
}
}
}
void main(void)
{
T0_Init();
G=0;
H=0;
I=0;
J=0;
while(1)
{
Start_Scan(); //开始键扫描
if((flag==0)&(s_flag==1)) //当开始键没按下及没有人违规时才可进行时间调整
{
Time_Scan();
}
if((flag==1)&(s_flag==0))//当开始键按下及有人抢答才进行开始回答计时倒计时
{
led=0;
if(K_Time==0)
{
delay(10);
if(K_Time==0)
{
while(!K_Time);
TR0=0;
t0=0;
TR1=1;
}
}
}
if((flag==0)&(s_flag==1)) //违规
{
Select_Scan();
if(num!=0) //开始键没有按下时,有人按下了抢答器,则置违规标志位
{
fall_flag=1;
led=0;
}
}
if((flag==1)&(s_flag==1)) //如果开始键按下且抢答键没有人按下,则进行八路抢答键扫描
{
Select_Scan();
}
display(); //显示到数码管上
}
}
void timer0(void) interrupt 1//定时器0
{
TH0=(65536-2000)/256; //2ms
TL0=(65536-2000)%256;
if(b_flag) //开始(START)键按下,嘟一声(长1秒),表示开始抢答
{
beep=~beep;
}
else
beep=1;
if(s<5) //抢答时间快到报警,每1秒响一声且红灯闪烁,响5声
{
if(s%1==0)
{
b_flag=1;
led=0;
}
else
{
b_flag=0;
led=1;
}
}
t0++;
if(t0==500) //1秒
{
t0=0;
s--;
b_flag=0; //关闭开始键按下响一秒的嘟声
if(s==-1)
{
s=20;
TR0=0;
flag=0; //显示F FF
s_flag=1;
num=0;
led=1;
}
}
}
void timer1(void) interrupt 3 //定时器1处理有人按下抢答器嘟一声(长1秒)
{
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;
beep=~beep;
t1++;
if(t1==500)
{
t1=0;
TR1=0;
}
}
到了这里,关于基于C语言的单片机八路抢答器课程设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!