篮球计分器.docx
《篮球计分器.docx》由会员分享,可在线阅读,更多相关《篮球计分器.docx(40页珍藏版)》请在冰豆网上搜索。
![篮球计分器.docx](https://file1.bdocx.com/fileroot1/2023-2/25/12bb4dd6-8837-4edd-822f-908e5854b861/12bb4dd6-8837-4edd-822f-908e5854b8611.gif)
篮球计分器
课题:
篮球计时计分器
班级:
08通信工程
(1)班
学号:
E08680117
姓名:
*********
指导教师:
*******
教学时间:
第19~20周
学年学期:
2010~2011学年第1学期
小故事
刚开始碰篮球时很陌生,因为不知道只是拿来干嘛的,整天那个球乱跑,但后来才知道,篮球是那么有意思——有喜有悲。
而小时候在打比赛的时候,也没有计分的东西,用人工计分,也没有时间限制,真正想打比赛的时候,总会有点不准确。
现在我设计了一个功能齐全的篮球计时计分器,又有报警提示,有24秒违例。
可以运用到平时篮球生活当中。
其实我还有篮球天赋,我觉得很是光荣啊。
有一次总决赛,我所在的红队和蓝队到了巅峰对决,只剩下最后的1分钟,比分是40:
36,但却是,我红队控球进攻。
为了把握最后赢的希望,虽然全队已经体力不支,但还想凭着最后的一分钟,赢得胜局。
我们打得非常顽强,进攻24秒开始倒计时,到了最后的40秒,开始有报警提示,说明时间已经所剩不多了
最后30秒,我想上场,教练同意了。
我拿到球,带球过人,一个上篮,球进了。
40:
38,我们落后。
对方发球,正以为比赛就这样结束时,我一个抢断,将球抢过来,我很不稳。
即使这样,我也只能投三分球,因为这样才可以锁定胜局,我仿佛心里打了一个镇定剂,把握好角度,投!
球在篮筐滚了几圈,我们都提心吊胆,有些性急的跳了起来,大喊“进,进!
”进了“嘟~比赛结束”裁判吹了哨子。
全场欢呼,我们留下了开心的眼泪
这就是篮球,我生命中不可磨灭的东西,有喜有悲,有笑有痛,篮球,让我的生活变得多彩!
1、设计内容:
本系统是采用单片机AT89C51作为本设计的核心元件。
利用7段共阴LED作为显示器件。
在此设计中共接入了2个4联7段共阴LED显示器,一个用于记录红队的分数,2个LED显示器显示范围可达到0~255分,基本满足赛程需要。
当比赛队得1分时,按下KEY1键加1分,得2分时按KEY22键加2分,得3分时按下KEY3键加3分。
如分数计错需减分时,每按一次KEY4键减1分,按KEY5键实现复位功能,KEY0实现复位功能。
采用单片机控制是这个系统按键操作使用简洁,LED显示,安装方便。
解决了篮球比赛计数器的安装问题,节约了线材,适合在各种规模的体育场馆使用,完全可以代替传统的用钟表进行计时的方法,当然稍加改动也可以用于其他球类比赛,是体育器材向智能化发展的一个实例。
2、设计任务和要求
任务:
设计一个用于赛场的篮球计时计分器。
要求:
1、能记录整个赛程的比赛时间,并能随时实现暂停。
2、能随时刷新甲、乙两队在整个过程中的比分。
3、中场交换比赛场地时,能自动交换甲、乙两队比分的位置。
4、比赛中场和结束时,能发出报警声。
5、通过指示灯指示上下半场。
6、当比赛时间需要回倒时,能通过按键实现回表。
7、加分有误时可通过按键实现减分调整。
3、设计原理
3.1AT89C51简介
单片机是在一块芯片中集成了CPU、RAM、ROM、定时/计数器和多功能I/O口等计算机所需要的基本部件的大规模集成电路,又称MCU。
其以体积小、功能全、性价比等诸多优点而独具特色,在工业控制、尖端武器、通信设备、家用电器等嵌入式应用领域中独占鳌头。
如果说C语言程序设计课程设计的基础课,那么单片机以其系统硬件构架完整、价格低廉、学生能动手等特点,成为工科学生硬件设计基础课。
3.2数码管显示原理
本设计采用共阴极数码显示器,通常,共阴极接低电平(一般接地),其它管脚接段驱动电路输出端。
当某段驱动电路的输出端为高电平时,该端所连接的字符导通并点亮,根据发光字段的不同组合可显示出各种数字或字符。
同样,要求段驱动电路能提供额定的段导通电流,还需根据外接电源及额定段导通电流来确定相应的限流电阻。
本次设计在显示模块用到的是一个4位一体和2个两位一体共阴极数码管,共有8个代码输入口和8个位选输入口,采用排阻提供上拉电流数码管,以保证有足够大的电流点亮数码管,采用动态驱动,使各位数码管逐个轮流受控显示,这就是动态驱动,由于扫描速度极快,显示效果与静态驱动相同,其具体图形如下图所示
数码管的接口有静态接口和动态接口两种。
静态接口为固定显示方式,无闪烁,其电路可采用一个并行口接一个数码管,数码管的公共端按共阳接VCC,本次课程设计由于所需数码管较少,故可用些种方法接线。
这种接法占用接口多,仅能接少量数码管。
动态接口采用各数码管循环轮流显示的方法,当循环显示的频率较高时,利用人眼的暂留特性,看不出闪烁显示现象,这种显示需要一个接口完成字形码的输出,另一接口完成各数码管的轮流点亮。
共阴极的代码可从下表查询
共阴极数码管显示
显示
小数点
G
F
E
D
C
B
A
HE代码
0
0
0
1
1
1
1
1
1
3FH
1
0
0
0
0
0
1
1
0
06H
2
0
1
0
1
1
0
1
1
5BH
3
0
1
0
0
1
1
1
1
4FH
4
0
1
1
0
0
1
1
0
66H
5
0
1
1
0
1
1
0
1
7DH
6
0
1
1
1
1
1
0
1
07H
7
0
0
0
0
0
1
1
1
7FH
8
0
1
1
1
1
1
1
1
6FH
9
0
1
1
0
1
1
1
1
40H
3.3系统总体方案
为了完成上述功能要求,篮球比赛计分器系统整体结构如下图所示,包括:
AT89C51,时钟及复位电路、按键电路、及LED显示器。
下图也是该电路的原理框图。
4、硬件设计电路图
5、软件设计
本次单片机课程设计软件设计部分采用模块化程序设计,程序部分由主程序、T0中断程序、扫描显示子程序、计时加(减)1秒的子程序、暂停子程序、快表和回表子程序、延时子程序等组成.其程序流程图如图9图10。
图9主程序流程图
图10扫描刷新显示子程序流程图
3.2软件设计具体过程
软件设计部分采用模块化程序设计,用C语言编写。
Keil是美国KeilSoftware公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
KeilC51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。
另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到KeilC51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。
在开发大型软件时更能体现高级语言的优势。
程序部分由主程序、T0中断程序、扫描显示子程序、计时加(减)1秒的子程序、暂停子程序、快表和回表子程序、延时子程序等组成。
6、程序清单
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineTH_value0xb1
#defineTL_value0xe0//定时器工作于方式1,每20ms产生一个中断
sbitspeak=P3^7;
sbitext=P3^2;
sbitled=P3^4;
/**********BCD码字***************/
ucharcodebcd[]={
0x00,0x01,0x02,0x03,
0x04,0x05,0x06,0x07,
0x08,0x09,0x0A,0x0B,
0x0C,0x0D,0x0E,0x0F
};
/************0~9数字显示**************/
ucharcodetable[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00};
ucharmunite;//比赛剩余分位数
ucharsecond;//比赛剩余秒位数
ucharpart;//当前比赛的节次
uchars24;//24秒标志
ucharred_mark;//红队得分
ucharblue_mark;//蓝队得分
ucharkey_move;//设置位移动
ucharkey_red_add;//红队得分增加1
ucharkey_red_mul;//红队得分减少1
ucharkey_blue_add;//蓝队得分增加1
ucharkey_blue_mul;//蓝队得分减少1
ucharkey_pause;//暂停
ucharkey_reset;//24秒复位及进入下一节复位
uchartime_tick1,time_tick2;
ucharstation;//状态标志位
ucharflag;//跳亮标志位
uchartalk1,talk2,num,num1;//报警信号标志
/*******函数声明********/
voidinit();
voidinit_timer();
voidinit_extra();
ucharkey_scan();
voidscanf(ucharp,uchartw,ucharm,uchars,ucharr,ucharb);
voidscanf1(ucharp,ucharr,ucharb);
voidscanf2(uchartw,ucharr,ucharb);
voidscanf3(ucharm,ucharr,ucharb);
voidscanf4(uchars,ucharr,ucharb);
voidplay24();
voidplaystop1();
voidplaystop2();
/*********延时程序,t=1时,延时1ms************/
voiddelay(uchart)
{
inti,j;
for(j=0;jfor(i=0;i<110;i++);
}
/***********主程序************/
voidmain()
{
init();
init_timer();
init_extra();//初始化
while
(1)
{
if(station==0)//状态0:
比赛状态
{
scanf(part,s24,munite,second,red_mark,blue_mark);
if(time_tick1==50)
{
time_tick1=0;
if(second==0)//时间计数
{
if(munite==0)
{
if(part>=4)
{
talk2=1;//终场报警操作
TR0=0;//关闭定时器中断0
TR1=1;
}
else
{
talk2=1;//小节结束报警
TR1=1;
TR0=0;
}
}
else
{
munite--;
second=59;
}
}
else
second--;
if(s24==0)//24秒计数
{
TR0=0;
}
else
{
if(s24<2)
{
talk2=1;
TR1=1;
TR0=0;
key_pause=0;
}
elseif(s24<8)
{
talk1=1;
TR1=1;
}
s24--;//6秒提醒
}
}
if(second==0&&munite==0)//操作进入下一节比赛
{
if(key_reset==1)
{
s24=0x18;
part++;
key_reset=0;
if(part==10)
talk2=1;//比赛太久,报警
if(part<5)//判断是否为加时赛,不是,延长12分钟
{
munite=0x0c;
second=0x00;
}
else//加时赛,延长5分钟
{
munite=0x05;
second=0x00;
}
}
}
if(second!
=0||munite!
=0)//操作24秒复位
{
if(key_reset==1)
{
if(second<0x18&&munite==0)//当比赛剩余时间少于24秒时,sS4为当前剩余时间
{
key_reset=0;
s24=second;
}
else//当时间大于24秒时,S24复位为24秒
{
key_reset=0;
s24=0x18;
}
}
}
if(key_red_add==1)//红队得分操作加
{
key_red_add=0;
if(red_mark<0xff)
red_mark++;
}
if(key_red_mul==1)//红队得分操作减
{
key_red_mul=0;
if(red_mark>0)
red_mark--;
}
if(key_blue_add==1)//蓝队得分操作加
{
key_blue_add=0;
if(blue_mark<0xff)
blue_mark++;
}
if(key_blue_mul==1)//蓝队得分操作减
{
key_blue_mul=0;
if(blue_mark>0)
blue_mark--;
}
}
if(station==1)//比赛节次操作
{
TR1=1;
flag=0;
while(station==1)
{
if(flag==0)
scanf1(part,red_mark,blue_mark);
if(flag==1)
scanf(part,s24,munite,second,red_mark,blue_mark);
if(key_red_add==1)//比赛节次操作加
{
key_red_add=0;
if(part<0x09)
part++;
}
if(key_red_mul==1)//比赛节次操作减
{
key_red_mul=0;
if(part>1)
part--;
}
}
if(station!
=1)
{
TR1=0;
flag=0;
}
}
if(station==2)//24秒操作
{
TR1=1;
flag=0;
while(station==2)
{
if(flag==0)
scanf2(s24,red_mark,blue_mark);
if(flag==1)
scanf(part,s24,munite,second,red_mark,blue_mark);
if(key_red_add==1)//24秒操作加.MAX=24
{
key_red_add=0;
if(s24<0x18)
s24++;
}
if(key_red_mul==1)//24秒操作减
{
key_red_mul=0;
if(s24>0)
s24--;
}
}
if(station!
=2)
{
TR1=0;
flag=0;
}
}
if(station==3)//计时分操作
{
TR1=1;
flag=0;
while(station==3)
{
if(flag==0)
scanf3(munite,red_mark,blue_mark);
if(flag==1)
scanf(part,s24,munite,second,red_mark,blue_mark);
if(key_red_add==1)//分操作加,MAX=60
{
key_red_add=0;
if(munite<0x3c)
munite++;
}
if(key_red_mul==1)//分操作减
{
key_red_mul=0;
if(munite>0)
munite--;
}
}
if(station!
=3)
{
TR1=0;
flag=0;
}
}
if(station==4)//计时秒操作
{
TR1=1;
flag=0;
while(station==4)
{
if(flag==0)
scanf4(second,red_mark,blue_mark);
if(flag==1)
scanf(part,s24,munite,second,red_mark,blue_mark);
if(key_red_add==1)//秒操作加,MAX=60
{
key_red_add=0;
if(second<0x3c)
second++;
}
if(key_red_mul==1)//秒操作减
{
key_red_mul=0;
if(second>0)
second--;
}
}
if(station!
=4)
{
TR1=0;
flag=0;
}
}
}
}
/************初始化************/
voidinit()
{
munite=0x01;
second=0x00;
red_mark=0x00;
blue_mark=0x00;
part=0x01;
s24=0x18;
station=0x00;
key_pause=0;
key_move=0x00;
key_red_add=0x00;
key_red_mul=0x00;
key_blue_add=0x00;
key_blue_mul=0x00;
key_reset=0x00;
flag=0x00;
}
/************定时器0初始化**************/
voidinit_timer()
{
TMOD=0x11;
TH0=TH_value;
TL0=TL_value;
TH1=TH_value;
TL1=TL_value;
ET0=1;
ET1=1;
time_tick1=0;
time_tick2=0;
}
/**************外部中断源初始化****************/
voidinit_extra()
{
EX0=1;
EX1=1;
IT0=1;
IT1=1;
EA=1;
}
/*****************定时器0***************/
voidtimer0()interrupt1
{
time_tick1++;
TH0=TH_value;
TL0=TL_value;
}
/*************定时器1***************/
voidtimer1()interrupt3
{
EA=0;
TH1=TH_value;
TL1=TL_value;
time_tick2++;
if(time_tick2==50)
{
led=~led;
time_tick2=0x00;
if(flag==0)
flag=1;//跳亮标志位
else
flag=0;
}
if(talk1==1)
{
EA=0;
TH1=0xFD;
TL1=0xF7;
EA=1;
speak=~speak;
num++;
if(num==200)
{
num=0;
talk1=0;
TR1=0;
}
}
if(talk2==1)
{
EA=0;
TH1=0xFD;
TL1=0xF7;
EA=1;
speak=~speak;
num++;
if(num==200)
{
num1++;
num=0;
if(num1==4)
{
num1=0;
talk2=0;
TR1=0;
}
}
}
EA=1;
}
/***********外部中断0************/
voidextra0()interrupt0
{
if(key_pause==1)
{
key_pause=0;
TR0=0;
}
else
{
if(s24==0)
;
else
{
key_paus