知方号

知方号

基于51单片机篮球计时计分器的设计(附源码)<蜂鸣器复位按钮原理图>

基于51单片机篮球计时计分器的设计(附源码)

摘    要篮球计时计分器是一种应用非常广泛比赛计时工具,对现代社会越来越重要。此篮球计时计分器在硬件方面主要采用STC89C51RC单片机作为主控核心,由独立按键、共阳数码管显示屏显示。STC89C51RC单片机是由STC公司推出的,功耗小,电压可选用4~6V电压供电;所有程序编写完成后,在Keil软件中进行调试,确定没有问题后,烧写到单片机上进行测试。此设计主要由独立按键采集数据到单片机进行处理再通过数码管显示出来,本论文主要研究了数码管及独立按键,对硬件连接方案进行了详尽的介绍,在软件方面算法也进行了论述。目录前  言第一章  工作原理1.1设计目标1.1.1基本功能第二章  硬件设计与原理2.1 总设计框图2.2 硬件设计分析2.2.1 电源的设计2.2.2 单片机最小系统2.2.3 显示系统2.2.4 按键调整电路2.2.5 蜂鸣器电路第三章  软件设计与分析3.1 软件设计的组成3.2 源程序第四章  软件仿真4.1 PROTEUS简介4.2仿真图4.3原理图4.4 元件清单4.5 硬件结果图总结致  谢参考文献前  言

最近几年来,随着科技的飞速发展,单片机领域正在不断的走向社会各个角落,还带动传统控制检测日新月异更新。在实时运作和自动控制的单片机应用到系统中,单片机如今是作为一个核心部件来使用,仅掌握单片机方面知识是不够的,还应根据其具体硬件结构,以及针对具体应用对象特点的软件结合,加以完善。“单片机原理及应用课程设计”是电子类专业的学科基础科,它是继“汇编语言程序设计”,“接口技术”等课程之后开出的实践环节课程。

第一章  工作原理1.1设计目标1.1.1基本功能51单片机+按键+蜂鸣器+数码管数码管:2个4位一体共阳数码管具有12分钟倒计时功能,精确到秒,能够暂停最后10秒,声音和指示灯报警功能能记录两队分数,并且能够加减功能半场比赛结束能够交换两队比分具有时间暂停功能,可以快进或者快退时间51单片机型号:STC89C51RC、AT89C51单片机任选一个C语言编程第二章  硬件设计与原理

以STC89C51RC单片机为核心,起着控制作用。系统包括数码管显示电路、复位电路、时钟电路、按键调整电路和蜂鸣器电路。设计思路分为六个模块:复位电路、晶振电路模、STC89C51RC、数码管显示电路、按键调整电路和蜂鸣器电路这六个模块。

2.1 总设计框图

2.2 硬件设计分析2.2.1 电源的设计

系统电源使用外接直流5伏。

USB是通用串行总线(Universal Serial Bus)接口的简称。它是目前使用比较广泛的电脑接口之一,主要版本有1.0、1.1和最新的2.0三种版本。根据USB总线的工业标准,它可以提供额定功率为5V/500mA的电源供USB设备使用。

2.2.2 单片机最小系统

51单片机是对目前所有兼容intel 8031指令系统的单片机的统称。该系列单片机的始祖是intel的8031单片机,后来随着技术的发展,成为目前广泛应用的8为单片机之一。单片机是在一块芯片内集成了CPU、RAM、ROM、定时器/计数器和多功能I/O口等计算机所需要的基本功能部件的大规模集成电路,又称为MCU。51系列单片机内包含以下几个部件:

一个8位CPU;一个片内振荡器及时钟电路;

4KB的ROM程序存储器;

一个128B的RAM数据存储器;

寻址64KB外部数据存储器和64KB外部程序存储空间的控制电路;

32条可编程的I/O口线;

两个16位定时/计数器;

一个可编程全双工串行口;

5个中断源、两个优先级嵌套中断结构。

如图2-2-1所示为STC89C51RC单片机基本构造,其基本性能介绍如下:

图2-2-1 STC89C51RC单片机

STC89C51RC本身内含40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中端口,3个16位可编程定时计数器,2个全双工串行通信口,STC89C51RC可以按照常规方法进行编程,但不可以在线编程。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的Flash存储器可有效地降低开发成本。

STC89C51RC的主要特性如下表所示:

兼容MCS―51指令系统32个可编程I/O线4k字节可编程闪烁存储器可编程UARL通道三个16位可编程定时/计数器中断时钟频率0-24MHz2个外部中断源,共8个中断源256×8bit内部RAM2个读写中断口线可直接驱动LED软件设置睡眠和唤醒功能低功耗空闲和掉电模式表2-2-1 STC89C51RC主要功能描述

STC89C51RC为40脚双列直插封装的8位通用微处理器,采用工业标准的C51内核,在内部功能及管脚排布上与通用的89c51相同,其主要用于会聚调整时的功能控制。功能包括对会聚主IC内部寄存器、数据RAM及外部接口等功能部件的初始化,会聚调整控制,会聚测试图控制,红外遥控信号IR的接收解码及与主板CPU通信等。主要管脚有:XTAL1(19脚)和XTAL2(18脚)为振荡器输入输出端口,外接12MHz 晶振。RST/Vpd(9脚)为复位输入端口,外接电阻电容组成的复位电路。VCC(40脚)和VSS(20脚)为供电端口,分别接+5V电源的正负端。P0~P3 为可编程通用I/O脚,其功能用途由软件定义,在本设计中,P0端口(32~39脚)被定义为N1功能控制端口,分别与N1的相应功能管脚相连接,13脚定义为IR输入端,10脚和11脚定义为I2C总线控制端口,分别连接N1的SDAS(18脚)和SCLS(19脚)端口,12脚、27脚及28脚定义为握手信号功能端口,连接主板CPU的相应功能端,用于当前制式的检测及会聚调整状态进入的控制功能。

P0口:P0口是一组8位漏极开路型双向I/O 口,也即地址/数据总线复用口。作为输出口用时,每位能吸收电流的方式驱动8个TTL逻辑门电路,对端口P0写“1”时,可作为高阻抗输入端用。在访问外部数据存储器或程序存储器时,这组口线分时转换地址(低8位)和数据总线复用,在访问期间激活内部上拉电阻。在Flash 编程时,P0口接收指令字节,而在程序校验时,输出指令字节,校验时,要求外接上拉电阻。

P1口:P1是一个带内部上拉电阻的8位双向I/O口,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口。作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。与AT89C51不同之处是,P1.0和P1.1还可分别作为定时/计数器2 的外部计数输入(P1.0/T2)和输入(P1.1/T2EX)。Flash编程和程序校验期间,P1接收低8位地址。

P2口:P2是一个带有内部上拉电阻的8 位双向I/O口,P2的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对端口P2写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口,作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。在访问外部程序存储器或16位地址的外部数据存储器(例如执行MOVX @DPTR指令)时,P2口送出高8位地址数据。在访问8位地址的外部数据存储器(如执行MOVX @RI指令)时,P2口输出P2锁存器的内容。Flash编程或校验时,P2亦接收高位地址和一些控制信号。

P3口:P3口是一组带有内部上拉电阻的8位双向I/O口。P3口输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。对P3口写入“1”时,它们被内部上拉电阻拉高并可作为输入端口。此时,被外部拉低的P3口将用上拉电阻输出电流(IIL)。P3口除了作为一般的I/O口线外,更重要的用途是它的第二功能P3口还接收一些用于Flash 闪速存储器编程和程序校验的控制信号。

RST:复位输入。当振荡器工作时,RST引脚出现两个机器周期以上高电平将使单片机复位。

ALE/PROG:当访问外部程序存储器或数据存储器时,ALE(地址锁存允许)输出脉冲用于锁存地址的低8位字节。一般情况下,ALE仍以时钟振荡频率的1/6输出固定的脉冲信号,因此它可对外输出时钟或用于定时目的。要注意的是:每当访问外部数据存储器时将跳过一个AL脉冲。对Flash存储器编程期间,该引脚还用于输入编程脉冲(PROG)。如有必要,可通过对特殊功能寄存器(SFR)区中的8EH单元的D0位置位,可禁止ALE操作。该位置位后,只有一条 MOVX 和MOVC指令才能将ALE激活。此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE禁止位无效。

PSEN:程序储存允许(PSEN)输出是外部程序存储器的读选通信号,当STC89C51RC由外部程序存储器取指令(或数据)时,每个机器周期两次PSEN有效,即输出两个脉冲。在此期间,当访问外部数据存储器,将跳过两次PSEN信号。

EA/VPP:外部访问允许。欲使CPU仅访问外部程序存储器(地址为0000H―FFFFH),EA端必须保持低电平(接地)。需注意的是:如果加密位LB1被编程,复位时内部会锁存EA端状态。如EA端为高电平(接Vcc端),CPU则执行内部程序存储器中的指令。Flash存储器编程时,该引脚加上+12V的编程允许电源Vpp,当然这必须是该器件是使用12V编程电压Vpp。

XTAL1:振荡器反相放大器的及内部时钟发生器的输入端。

XTAL2:振荡器反相放大器的输出端。

单片机最小原理图如图2-2-2所示。

图2-2-2 单片机最小系统单片机最小系统说明:

时钟信号的产生:在MCS-51芯片内部有一个高增益反相放大器,其输入端为芯片引脚XTAL1,其输出端为引脚XTAL2。而在芯片的外部,XTAL1和XTAL2之间跨接晶体振荡器和微调电容,从而构成一个稳定的自激振荡器,这就是单片机的时钟振荡电路。

时钟电路产生的振荡脉冲经过触发器进行二分频之后,才成为单片机的时钟脉冲信号。

一般地,电容C2和C3取30pF左右,晶体的振荡频率范围是1.2-12MHz。如果晶体振荡频率高,则系统的时钟频率也高,单片机的运行速度也就快。

单片机复位使CPU和系统中的其他功能部件都处在一个确定的初始状态下,并从这个状态开始工作。单片机复位条件:必须使9脚加上持续两个机器周期(即24个振荡周期)的高电平。

2.2.3 显示系统

图2-2-3 数码管显示电路

2.2.4 按键调整电路图2-2-4 按键调整电路2.2.5 蜂鸣器电路图2-2-5 蜂鸣器电路第三章  软件设计与分析3.1 软件设计的组成

该系统由延时子函数、蜂鸣器子函数、初始化子函数、调节比赛时间数码管显示子函数、比赛开始数码管显示子函数、甲队得分数码管显示子函数、乙队得分数码管显示子函数、按键扫描子函数、定时器0中断子函数、主函数和数据定义这几部分组成。

图3-1-1 主程序流程图

图3-1-2 倒计时程序流程图

第四章  软件仿真4.1 PROTEUS简介

Proteus ISIS是英国Labcenter公司开发的电路分析与实物仿真软件。它运行于Windows操作系统上,可以仿真、分析(SPICE)各种模拟器件和集成电路,该软件的特点是:

(1)现了单片机仿真和SPICE电路仿真相结合。具有模拟电路仿真、数字电路仿真、单片机及其外围电路组成的系统的仿真、RS232动态仿真、I2C调试器、SPI调试器、键盘和LCD系统仿真的功能;有各种虚拟仪器,如示波器、逻辑分析仪、信号发生器等。

(2)支持主流单片机系统的仿真。目前支持的单片机类型有:68000系列、8051系列、AVR系列、PIC12系列、PIC16系列、PIC18系列、Z80系列、HC11系列以及各种外围芯片。

(3)提供软件调试功能。在硬件仿真系统中具有全速、单步、设置断点等调试功能,同时可以观察各个变量、寄存器等的当前状态,因此在该软件仿真系统中,也必须具有这些功能;同时支持第三方的软件编译和调试环境,如Keil C51 uVision2等软件。

(4)具有强大的原理图绘制功能。

可以仿真51系列、AVR、PIC、ARM、等常用主流单片机。还可以直接在基于原理图的虚拟原型上编程,再配合显示及输出,能看到运行后输入输出的效果。配合系统配置的虚拟逻辑分析仪、示波器等,Proteus建立了完备的电子设计开发环境。

在PROTEUS绘制好原理图后,调入已编译好的目标代码文件:*.HEX,可以在PROTEUS的原理图中看到模拟的实物运行状态和过程。 PROTEUS 是单片机课堂教学的先进助手。

PROTEUS不仅可将许多单片机实例功能形象化,也可将许多单片机实例运行过程形象化。前者可在相当程度上得到实物演示实验的效果,后者则是实物演示实验难以达到的效果。

它的元器件、连接线路等却和传统的单片机实验硬件高度对应。这在相当程度上替代了传统的单片机实验教学的功能,例:元器件选择、电路连接、电路检测、电路修改、软件调试、运行结果等。

课程设计是学生走向就业的重要实践环节。由于PROTEUS提供了实验室无法相比的大量的元器件库,提供了修改电路设计的灵活性、提供了实验室在数量、质量上难以相比的虚拟仪器、仪表,因而也提供了培养学生实践精神、创造精神的平台。         

4.2仿真图4.3原理图4.4 元件清单4.5 硬件结果图总结

经过近三个月的努力,终于顺利完成了设计。刚开始,我们头绪不是很清楚,不知道从哪里入手,但通过老师的耐心指导并和同学认真研究设计课题,跑图书馆查资料、确定基本设计方案、对所用芯片功能进行查找、调试、上机仿真等,经历了一次次的困难,却积累了很多宝贵的经验。在整个设计的过程中遇到的问题主要有以下三点,第一:基础知识掌握的不牢固,主要表现在一些常用的电路的形式和功能不清楚,对书本上的内容理解不够透彻。第二:对一些常用的应用软件缺少应用,体现在画电路图和系统的仿真的时候,对这些软件的操作不熟练,浪费了很多时间。第三:相关知识掌握的不够全面,缺少系统设计的经验。

这次设计进一步端了我的学习态度,学会了实事求是,严谨的作风,对自己要严格要求,不能够一知半解,要力求明明白白。急于求成是不好的,我有所感受。如果省略了那些必要的步骤,急于求成,不仅会浪费时间,还会适得其反。我觉得动手之前,头脑里必须清楚该怎么做,这一点是很重要的。就目前来说,我的动手能力虽然差一点,但我想,通过我的不懈努力,在这方面,我总会得到提高。这一点,我坚信。因为别人能做到的,我也一定能做到。

在此次的设计中我最大的体会就是进一步认识到了理论联系实践的重要性。一份耕耘,一份收获。通过这段时间的设计,让我明白科学的思维方法和学习方法是多么重要,只有这样才能够有很高的效率,才能够让自己的工作更完美。总而言之,此次设计让我学到了好多平时在课堂上学不到的东西,增加了我的知识运用能力,增强我的实际操作能力。谢谢老师给我们提供这么好的机会,为我们之后走向社会奠定了一个好的基础。

本次设计让我学到了很多,也学会到了要怎么样去面对困难,不要对知识一知半截,要有的求实的能力,通过老师的帮助我学到了很多在平时的没有注意到的动东西及知识,更美没有深入的的去理解,通过这次我要更加的明确自己。更要注重自己在各方面的锻炼能力,把握机会。这次的设计非常的感谢老师们。

单片机源程序如下:

#includetypedef unsigned char uchar;typedef unsigned int  uint;uchar code seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //对应数码管显示数字0-9int m=1,n=0,x=0,y=0,i=0,h=0,k;//定义全局变量并初始化,m,n表示分钟与秒,x,y表示甲乙两队分数sbit P1_0=P1^0;sbit P1_1=P1^1;sbit P1_2=P1^2;sbit P1_3=P1^3;sbit P1_4=P1^4;sbit P1_5=P1^5;sbit P1_6=P1^6;sbit P1_7=P1^7;sbit P3_0=P3^0;sbit P3_1=P3^1;sbit P3_2=P3^2;sbit P3_3=P3^3;sbit P3_6=P3^6;sbit P3_7=P3^7;void delay(uint x)//定义延时程序,通过设置参数x,改变延时时间长度{              while(x--)              {                            uint y;                            for(y=0;y0)              //当按下P3_0并且甲队分数大于0的时候              {                            delay(1);                                                                      //延时去抖                            while(P3_0==0);                            x--;                                                                         //甲队减1分              }                           if(P3_1==0&&x>0)              //当按下P3_1并且乙队分数大于0的时候              {                            delay(1);                            while(P3_1==0);                            y--;                                                                         //乙队减1分              }}void tiaoshi()                                                                                                  //定义调时程序{              if(P3_2==0)                                                                                    //当按下P3_2的时候              {                            delay(1);                                                                      //延时去抖                            if(P3_2==0)                            {                                          n++;                                                                      //秒位加1                                          if(n==60)//当秒位到60的时候                                          {                                                        m++;//分位加1,并且秒位变1                                                        n=1;                                          }                            }              }              if(P3_3==0)                                                                                    //当按下P3_3的时候              {                            delay(1);                                         if(P3_3==0)                            {                                          n--;//秒位减一                                          if(n==0)                                                                                             //当秒位减到0的时候,分位减一,并且秒位变59                                          {                                                        m--;                                                                     n=59;                                          }                            }              }}void jiaohuan()                                                                                      //定义比分交换程序{              int t;                                                                                                    //定义中间变量t              if(P1_7==0)                                                                                      //当P1_7按下的时候              {                            delay(1);                                                                        //延时去抖                            while(P1_7==0);                            t=x;                                                                      //利用中间变量t,将甲乙两队比分交换                            x=y;                            y=t;                            display(m,n,x,y);                                          //刷新数码管              }}void zanting()                                                                                                  //定义暂停程序{              if(P1_0==0)                                                                                                                //当P1_0按下的时候              {                            delay(1);                                                                                      //延时去抖                            while(P1_0==0);                            EA=0;                                                                                                    //关中断,进入死循环                            while(1)                            {                                          display(m,n,x,y);                                          if(P1_0==0)                            //当P1_0再次按下的时候,跳出死循环                                          {                                                                     delay(1);                                                        while(P1_0==0)                                                        EA=1;                                                        break;                                                       }                            }              }}void baojing()                                                                                    //定义报警程序{               if((m==0)&&(n1))              //判断当倒计时只剩下10秒的时候              {                            P3_7=1;                                                                                   //使P3_7和P3_6同时间隔输出高低电平,点亮发光二极管和使蜂鸣器蜂鸣                            P3_6=1;                            delay(20);                            P3_7=0;                            P3_6=0;                            delay(20);              }}void jieshu()                                                                                    //定义结束子程序{              M:              if(h==1)                                                                     //当时间条件满足时,关闭中断,使数码管保持状态显示                            {                                          EA=0;                                          delay(20);            m=0;                                n=0;                                P3_6=1;                                P3_7=1;                                delay(200);                                          P3_7=0;                                          P3_6=0;                                while(1)                                {                                                        display(m,n,x,y);                                                          jiafen();                                                          jianfen();                                                          jiaohuan();                                                          if(P1_0==0)                                          //当P1_0再次按下的时候,跳出循环                                              {                                                                                          delay(1);                                                                      while(P1_0==0)                                                                       {                                                                                    EA=1;                                                                                    m=10;    //重新赋予时间初始值开始下半场比赛                                                                                    n=0;                                                                                    h=0;                                                                                    goto M ;                                                                      }                                                                                   }                                          }                            }}void main()                                                                                                                //定义主程序{              TMOD=0x01;                                                                                                  //初始化程序              EA=1;                                                                     ET0=1;              P3_7=0;              P0=0xff;              P2=0x00;              if(P1_0==0)                            //第一次按下P1_0,单片机启动,并显示初始值              {                                                                                                    //由于调用了一次暂停功能,会显示初始值                            TH0=0xb1;                            TL0=0x10;                            TR0=1;                                                                                                                //启动定时器                            P3=0xff;                                         P1=0x7f;                            P3_7=0;                            P1_7=1;                            while(1)                            {                                           jiafen();                                       //加分子程序                                          jianfen();                                   //减分子程序                                          tiaoshi();                                              //调时子程序                                          jiaohuan();                                   //比分交换子程序                                          zanting();                                             //暂停子程序                                          baojing();                                             //报警子程序                                          if((m==0)&&(n==1))                 //判断结束子程序的调用条件                                          {                                                        h=1;                                          }                                          jieshu();                                                //结束子程序                            }              }}复制代码以上图文的Word格式文档下载(内容和本网页上的一模一样,方便保存):

基于51单片机篮球计时计分器的设计.doc(808.29 KB, 下载次数: 473)2018-12-11 23:03 上传点击文件名下载附件下载积分: 黑币 -5

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。