单片机篮球计分器课程设计报告

电气工程及其自动化学院学生课程设计报告

题目:篮球记分器课程设计报告

指导老师:梁建伟

电气工程及其自动化学院

专业班级:电气131

姓名:杨昊东

1月14日


一、概述

目前,篮球计分器的设计是通过AT89C52单片机芯片的工作原理在原来的篮球计分系统的按键计分的基础上进行比赛比分的加减及启动暂停等操作,在基础功能上增加了1s/次的24s倒计时报警功能。

本论文以一场篮球比赛具体计时计分方式为研究对象,以比赛规则为基础,对遥控篮球计分系统进行了分析和研究。该设计主要通过对单片机的工作原理及对单片机的应用,来实现一场模拟的篮球比赛的计时计分过程。在设计中使用了定时器T0中断来进行计时,显示分为计时和计分两部分,且都用动态扫描方式。主控芯片采用AT89C52,利用了keil软件进行C语言进行编程,proteus软件进行电路图仿真,完成设计目标及功能的正常实现,再使用电子元器件进行实物焊接后进行实物仿真。

普通篮球比赛采用人工计分,而使用单片机来进行控制,操作便捷,LED数码管显示简单易懂,安装方便。适合各种规模的篮球比赛,完全可以代替钟表型的人工计时计分,是体育器材实现智能化的一个例子,推动了电子在体育比赛中的应用和普及。

其基本功能有:

(1)当比赛开始按键按下时比赛开始,比赛时间倒计时,

(2)比赛过程中通过红外遥控进行比分控制和暂停指令。

(3)24s违规倒计时,遥控按键控制;中场比分交换,按键控制,

(4)比赛结束后通过复位按键进行清零,按下启动按键重新开始。

基本原理:

24秒计时器的总体参考方案框图如下图所示。它包括秒脉冲发生器、计数器、译码显示电路、报警电路和辅助时序控制电路(简称控制电路)等五个模块组成。其中计数器和控制电路是系统的主要模块。计数器完成24秒计时功能,而控制电路完成计数器的直接清零、启动计数、暂停/连续计数、译码显示电路的显示与灭灯、定时时间到报警等功能。http://retype.wenku.bdimg.com/retype/zoom/2af89d4ebceb19e8b8f6baf2?pn=3&x=0&y=0&raww=569&rawh=329&o=jpg_6_0_______&type=pic&aimh=277.5395430579965&md5sum=7a2074de0d468c49250bfd892120ddea&sign=8eadb79b0b&zoom=&png=552-5483&jpg=0-16514

秒脉冲发生器产生的信号是电路的时钟脉冲和定时标准,但本设计对此信号要求并不太高,故电路可采用单片机定时器。

译码显示电路由共阴极七段LED显示器组成。报警电路在实验中用发光二极管和鸣蜂器。

主体电路: 24秒倒计时。24秒计数芯片的置数端清零端共用一个开关,比赛开始后,24秒的置数端无效,24秒的倒数计时器的倒数计时器开始进行倒计时,逐秒倒计到零。选取“00”这个状态,通过组合逻辑电路给出截断信号,让该信号与时钟脉冲在与门中将时钟截断,使计时器在计数到零时停住。

二、篮球计分系统硬件设计

1.1 、 AT89C52单片机简介及工作原理 AT89系列单片机的内部结构中包括一般微型计算机里必需的基本功能及部件、RAM、ROM、定时/计数器和可编程的并行I/O口、可编程的串行口。这些基本的功能部件一般都挂靠在单片机的内部总线上,使用内部总线来传送数据信息和控制信息来达到目标的实现。

AT89C52单片机的内部有4个8位的并行I/O端口,分别为P0、P1、P2、P3。每个端口都有一个同名的特殊功能寄存器(锁存器)、一个输入缓冲和一个输出驱动器器。并行I/O口的控制是通过端口中的锁存器来进行控制的。 AT89C52内部基本结构

1.2 、 AT89C52单片机的I/O端口

0~P3 的可编程通用I/O 端口分别如下:

(1)P1口 :P1 口是由8个D触发器构成的一个可储存8位二进制码的P1口的特殊功能寄存器,其字节地址为90H;由场效应管和上拉电阻构成输出驱动器,来增加P1口所带负载能力;其中三态门1和2在输入和输出的时候作为缓冲器来使用。

P1口作为通用的I/O使用,有输出、读引脚、读锁存器三种工作方式。P1口能驱动4个LS TTL负载。通常将100μA的电流定义为一个LS TT负载的电流,所以P1口输入或输出电流不大于100μA。P1口的内部自带上拉电阻,不需要再另接上拉电阻。

在本设计的仿真实验中篮球计分系统的遥控芯片P1口接入5个按键,分别为启动按键、暂停按键、比分交换、判断得分队伍按键及1分、2分、3分进球得分按键。

(2)P0口 :P0口的特殊功能寄存器由8个D触发器构成,其字节地址为80H。P0口的输出驱动电路由上拉场效应管和驱动场效应管组成。控制电路包括一个与门、一个非门和一个多路开关,其余组成和P1口相同。

P0口既可以作为通用的I/O口来进行数据的输入和输出,同时,也可以作为地址/数据线来使用。在CPU控制信号的作用下,多路开关可以分别接通用锁存器的输出或者地址/数据输出。P0口作为通用I/O口使用时,P0口和P1口一样,有输出、读引脚和读锁存器3种工作方式,P0口内部没有自带上拉电阻,所以要使“1”信号正常输出,必须外接上拉电阻,阻值一般为100Ω~10KΩ。设计中,选用的是共阴7段LED数码管,P0口接显示电路的数码管段选,输入对应高电平,点亮对应的段。通过对段选的判断来进行显示电路的显示。

(3)P3口 :P3口也可作为AT89C51的一些特殊功能口,如下表所示: 口管脚 备选功能:

P3.0 RXD(串行输入口)P3.1 TXD(串行输出口)

P3.2 /INT0(外部中断0)

P3.3 /INT1(外部中断1)

P3.4 T0(计时器0外部输入)

P3.5 T1(计时器1外部输入)

P3.6 /WR(外部数据 存储器写选通)

P3.7 /RD(外部数据 存储器读选通)

P3口同时为闪烁编程和编程校验接收一些控制信号。 RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的低位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。

PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。

XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。 XTAL2:来自反向振荡器的输出。

(4)P2口 :P2口的特殊功能寄存器由8个D触发器构成,其字节地址为A0H。与P1口相比,P2口中多出来一个多路开关,可以实现通用I/O口的基本功能和地址输出两种功能。

当P2口用作通用的I/O口时,在“控制”端的作用下,多路开关转向锁存器Q端,构成一个准双向口,并具有输出、读引脚和读锁存器3种工作方式。当单片机执行访问片外读写存储(RAM)或片外制度存储(ROM)指令时,程序计数器或是数据指针的高8位地址需由P2.n引脚输出。P2口的负载能力和P1口相同,能驱动4个LS TTL负载。设计中,P2口连接显示电路的位选,共阴数码管的位选在实验中是低电平有效,通过位选来控制对应位的显示。P2口无需接上拉电阻。

(5)振荡器特性: 

  XTAL1和XTAL2分别为反向放大器的输入和输出。该反向放大器可以配置为片内振荡器。石晶振荡和陶瓷振荡均可采用。如采用外部时钟源驱动器件,XTAL2应不接。有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。

(6)芯片擦除 

整个PEROM阵列和三个锁定位的电擦除可通过正确的控制信号组合,并保持ALE管脚处于低电平10ms 来完成。在芯片擦操作中,代码阵列全被写“1”且在任何非空存储字节被重复编程以前,该操作必须被执行。 

此外,AT89C51设有稳态逻辑,可以在低到零频率的条件下静态逻辑,支持两种软件可选的掉电模式。 

在闲置模式下,CPU停止工作。但RAM,定时器,计数器,串口和中断系统仍在工作。在掉电模式下,保存RAM的内容并且冻结振荡器,禁止所用其他芯片功能,直到下一个硬件复位为止 。

(6)掉电模式 

在掉电模式下,振荡器停止工作,进入掉电模式的指令是最后一条被执行的指令,片内RAM和特殊功能寄存器的内容在终止掉电模式前被冻结。推出掉电模式的唯一方法是硬件复位。复位后将重新定义全部特殊功能寄存器但不改变RAM中的内容,在VCC恢复到正常工作电平前,复位应无效,且必须保持一定时间以使振荡器重新启动并且稳定的工作

二:显示器介绍

显示器是最常用的输出设备,其种类繁多,但在单片机系统设计中最常用的是发光二极管显示器(LED)和液晶显示器(LCD)两种。由于这两种显示器结构简单,价格便宜,接口容易实现,因而得到广泛的应用。液晶显示器分很多种类,按显示方式可分为段式,行点阵式和全点阵式。段式与数码管类似,行点阵式一般是英文字符,全点阵式可显示任何信息, 如汉字、图形、图表等 。

两者之间的区别: 

(1)二极本身发光, 液晶本身不发光,只是透射光。  

(2)二极管体积大,图像质量一般,适合作室外大屏幕,价格较低。液晶成本较高,面积无法做得很大,但图像质量很好,适合做显示器。  

(3)二极管耗电大,液晶耗电小。

 (4)二极管图像刷新率低,液晶的高  

LED显示器又称为数码管,LED显示器由8个发光二极管组成。中7个长条形的发光管排列成“日”字形,另一个点形的发光管在显示器的右下角作为显示小数点用,它能显示各种数字及部份英文字母。LED显示器有两种不同的形式:共阳极LED显示器和共阴极LED显示器如图2-2所示 。

error本次设计使用的是共阳极LED数码管。LED数码管实际上是由七个发光管组成8字形构成的,加上小数点就是8个。这些段分别由字母a,b,c,d,e,f,g,dp来表示。当数码管特定的段加上电压后,这些特定的段就会发亮,以形成我们眼睛看到的。代码对应表下面看表2-2。

表2-2代码对应表T2]GE3~M4R_E3`3CM5S1KCY

动态显示原理:通过片选段选择某个数码管显示指定数字然后延长20毫秒左右,再通过片选段选择其他数码管显示数字,以此不断循环重复,由于视觉暂留效果,这样就可以同时看到几个不同的数字。

三、 硬件电路设计

本次设计主要基于AT89C51单片机,主体的计时计分器系统框图如图3-1所示.由于实际问题,所以在焊接事物时用的是89c52,但其引脚功能结构与89c51大概是一样的,也就是说原来在at89c51环境下编译的程序也适用于C52.以下实物图可能在细节处跟最终做出来的有点出路,但这并不影响其功能。

 图3-1

GCZL_MOV({5%~TM~@{5V%$T

3.2 各部分具体设计方案

3.2。1振荡电路 

本次设计要使用到AT89C51单片机的时钟振荡功能。AT89C51中有一个用于构成内部震荡器的高增益反相放大器,引脚XTAL1和XTAL2分别是该放大器的输入和输出端。这个放大器与作为反馈元件的片外石英晶体或者陶瓷谐振器一起构成自激振荡器[7]。AT89C51的时钟主要分为两种方式:第一种是片内时钟振荡,另一种是外部时钟方式。本次设计采用的是第一种片内时钟振荡方式,通过在18和19端口外接石英晶体和振荡电容组成,这样既可产生本设计所需的时钟。振荡电路如图3-2所示

QWOV2}H6S8[S3[K1TFY39HX

  图3-2  12MHz晶振电路

3.2.2计时计分LED显示器设计

  本次设计的核心就是采用AT89C51设计出一整套计时计分器,以满足与篮球比赛的需要。本次设计的LED显示器采用的是动态驱动方式。

   动态显示驱动:使用数码管动态显示界面的显示方式,已成为在单片机的应用中最广泛的一种,动态驱动就是将每个数码管的8个显示的笔划“a,b,c,d,e,f,g,dp”这几个引脚的同名端相连接,同时给数码管公共极COM增加了位元件选通控制电路,该位元件选通通过各自的独立输入/输出线控制。若单片机依次输出了字形码,则所有的数码管必会接收到同样的字形码。但是,单片机对于位元件选通电路的控制则决定了最终是哪个数码管能够显示出字形。因此,我们若想所需的数码管灯亮,则只要打开所需对应的数码管的选通控制,而不打开相应选通控制的数码管就不会发光。动态驱动就是通过分时方法轮流控制各个LED数码管的COM端口,从而促使每个数码管轮流的接受控制并显示。数码管在依次显示的过程当中,会产生1ms~2ms的点亮时间,因为每个人都存在视觉暂留的现象,加之受到发光二极管余辉效应的影响和信号的扫描达到一定足够的速度,所以,人会接收到稳定的显示信息。

本次设计具体采用的LED为7SEG-MP×2-CA,

J~OY[UDZ[JE$YPAY~6{VCS9

即七段二位共阳极数码管。

片选段需接晶体管驱动。

3.2.3按键设计

P3.2口接的按键为暂停键,暂停期间无法加分和倒计时。P3.3接的是甲队的加分键,P3.4接的则是乙队加分键。而P3.5接的是清零复位键。如下图3-3所示

0ZHN`GGTW%T3~T}BL30)Z)A

图3-3按键设计

3.2.4报警设计

24秒倒计时到后,蜂鸣器响。

error

三、 软件设计方案 

在单片机应用系统的开发过程中,主要采用的有汇编语言和C语言。汇编语言比C语言繁琐,但是汇编语言能更充分的发挥指令系统的功能和效率,可以获得最简练的目标程序。而C语言的应用最为广泛,C语言能直接对计算机的硬件进行操作,而且语言灵活、程序结构良好、数据类型及运算符丰富、代码效率高、可移植性好。本次课程设计以C语言为程序设计语言。具体程序如下

 #include<reg51.h>

#define uchar unsigned char

#define uint8 unsigned int

uchar code

show_t[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

static uchar display_buf[10];

char xSc[3],ySc[3];

char tSc[4];

uchar uS_a=0,dS_a=0,hS_a=0,uS_b=0,dS_b=0,hS_b=0;

uchar suT=0,sdT=0,muT=0,mdT=0;

sbit fm_bt=P2^7;

void delay_t(int t)

{

 int tt;

 while(t--)

 {

  tt=300;

  while(tt--);

  }

 }

 void display_rt(uchar dis_code[])

 {

  char bit_disp2,bit_disp3,i;

  bit_disp3=0x20;

  bit_disp2=0x08;

  for(i=0;i<=9;i++)

  {

   P2=0xff;

   P3=0xff;

   P0=show_t[dis_code[i]];

   if(i<6)

   {

    bit_disp2=0x08;

    P3=~bit_disp3;

    P2=0xff;

    bit_disp3=bit_disp3>>1;

    }

    else

    {

     bit_disp3=0x20;

     P2=~bit_disp2;

     P3=0xff;

     bit_disp2=bit_disp2>>1;

     }

     delay_t(1);

     }

void alarm_spk()

{

    uint8 vTmp;

    for(vTmp=0;vTmp<5000;vTmp++)

    {

             fm_bt=~fm_bt;

      delay_t(150);

    }

}

void modify_sc()

{

    while(1)

    {

             display_rt(display_buf);

             while(P1==0xfd)

             {

                       uS_a++;

                       if(uS_a>9)

                       {

                                 dS_a++;

                                 uS_a=0;

                       }

                       if(dS_a>9)

                       {

                                 dS_a=0;

                                 hS_a++;

                       if(hS_a>9)

                       {

                                 uS_a=0;

                                 dS_a=0;

                                 hS_a=0;

                       }

                       display_buf[3]=uS_a;

                       display_buf[4]=dS_a;

                       display_buf[5]=hS_a;

                       display_rt(display_buf);

                       delay_t(60);

             }

             while(P1==0xfb)

             {

                       uS_b++;

                       if(uS_b>9)

                       {

                                 uS_b=0;

                                 dS_b++;

                       }

                       if(dS_b>9)

                       {

                                 dS_b=0;

                                 hS_b++;

                       }

                       if(hS_b>9)

                       {

                                 uS_b=0;

                                 dS_b=0;

                                 hS_b=0;

                       }

                       display_buf[0]=uS_b;

                       display_buf[1]=dS_b;

                       display_buf[2]=hS_b;

                       display_rt(display_buf);

                       delay_t(60);

             }

    }

}

}

void modify_st()

{

    uchar i=0;

    while(i<3600)

    {

             suT++;

             delay_t(1);

             if(suT>9)

             {

                       suT=0;

                       sdT++;

             }

             if(sdT>5)

             {

                       sdT=0;

                       muT++;

             }

             if(muT>9)

             {

                       muT=0;

                       mdT++;

             }

             if(mdT>9)

             {

                       suT=0;

                       sdT=0;

                       muT=0;

                       mdT=0;

             }

             display_buf[6]=suT;

             display_buf[7]=sdT;

             display_buf[8]=muT;

             display_buf[9]=mdT;

             display_rt(display_buf);

             i++;

             delay_t(5);

}

}

void key_sc()

{

    uchar key_bt,i;

    while(1)

    {

             P1=0xff;

             delay_t(80);

             key_bt=P1;

             switch(key_bt)

             {

                       case 0xfe:

                       for(i=0;i<9;i++)

                       {

                                 //display_buf[i]=0;

                                 display_rt(display_buf);

                       }

                       break;

                       case 0xfd:

                                 modify_sc();

                       break;

                       case 0xfb:

                                 modify_sc();

                       break;

                       case 0xf7:

                                 modify_st();

                       break;

             }

    }

}

void main(void)

{

    key_sc();

    //display_rt(d);

    //alarm_spk();

}

四、仿真与调试

单片机应用的仿真和调试主要从硬件及软件方面进行,在本次设计的篮球计时计分器中我主要使用的是Keil和Proteus ISIS软件

 软件简介 

1、 Keil软件简介   

KeilC51是基于80C51单片机内核,由德国Keil Software公司研制的一款实用、智能的C语言软件开发系统。与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。KeilC51已被完全集成到uVision2的集成开发环境中,这个集成开发环境包含:编译器,汇编器,实时操作系统,项目管理器,调试器。uVision2 IDE可为它们提供单一而灵活的开发环境。 

2、 Proteus 简介 

Proteus是世界上著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。是目前世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、AVR、ARM、8086和MSP430等,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、Keil和MPLAB等多种编译器。Proteus软件具有其它EDA工具软件的功能:原理布图、PCB自动或人工布线、SPICE电路仿真等Proteus又具有互动的电路仿真、仿真处理器及其外围电路的革命性特点。

4、 仿真结果 

完成硬件电路设计后,检查线路连接,确认连线没有错误。双击单片机AT89C51,用单击出现的对话框中的Program File按钮,在之前保存的位置找到经过Keil软件编译而生成的HEX文件,载入后点击“OK”按钮。然后单击开始仿真按钮进行仿真。

WPEZ0YTS~IN(QSP3J22II$8

注示:前面说了在仿真过程用的是AT89C51,但焊接实物的时候用的是AT89C52,C51的程序也可用于C52,而C52的程序不一定能够用于C51.

五、总结

本次课设是本人到目前为止觉得最有意义也是收获最大的一次实习。我掌握了部分AT89C51的知识。这次课设恰恰给我们提供了一个应用自己所学知识的平台。从通过理论设计,到仿真软件仿真,再到确定具体方案。整个过程都需要我充分利用所学的知识进行思考、借鉴。可以说,本次课设是针对前面所学的知识进行的一次比较综合的检验。总的来说,这次课设虽然累,但非常充实。

相关推荐