
1 绪论
1.1 本设计的研究背景和研究目的
乒乓球,中华人民共和国国球,是一种世界流行的球类体育项目。它的英语官方名称是“table tennis”,即“网上桌球”。乒乓球的名字起源于1990年。乒乓球的比赛赛制是以11分为一局,采用五局三胜(团体)或七局四胜制(单项)。比赛分团体、单项(男单、女单、男双、女双、混双)。
在中国,到处可见打乒乓球的人,以学生居多。因为,随着人们现代化节奏的加快,工作压力的增大,传统打乒乓球的方式受到运动设施、场地、环境的因素的影响,让人们对乒乓球运动减少了很多兴趣。随着科学技术的发展,人类进入信息化社会,信息社会的发展离不开电子产品的进步。现代电子产品发展的越来越快,于是人们将乒乓球与电子产品结合在一起,形成了乒乓游戏机。通过使用按键模拟球拍,发光二极管模拟乒乓球,进行乒乓球游戏的操作。
乒乓游戏机的出现解决了人类的很大难题。因为该产品不受运动设施、空间、场地、环境等因素的影响,在家即可进行操作。操作的同时,让操作者仿佛在真正的打乒乓球。而且该设计属于一种益智类设计,让人既可以锻炼身体,也可以锻炼智力。
1.2 国内外研究现状
第二次世界大战以后,电子计算机技术得到了突飞猛进的发展。电子计算机一代一代的更新的同时,软件设计也迅速发展。于是,1971年,世界上第一台电子游戏机出现了。随着电子技术的迅猛发展,电子游戏机进入了次世代,主要有三大游戏机厂商。分别为:SONY、微软和任天堂。
如今,大部分益智类游戏机属于电子游戏机,乒乓游戏机就属于电子游戏机。随着电子技术的突破,电子游戏机开始朝着“便携式”和“家庭化”方向发展,彩色电视的普及使大型游戏机的显像管和扫描版部分完全可以被彩色电视取代,使得微处理机部分与现实屏幕实现了分离。现在制成的游戏机只相当于一个信号发生器。如今乒乓游戏机已出现3D类,体感类等等类型。
乒乓游戏机不仅可以实现人们对乒乓球的热爱,又可以让人们在玩耍的同时进行身体锻炼和智力提高,具有明朗的前景。
1.3 本设计的任务和设计方法
1.3.1 设计任务
如今各种不同类型的游戏设备一直是消费领域的热点,本设计要求用低廉的成本设计出符合要求的游戏设备,要求操作方便,系统稳定度高。设计任务为:
(1)使用乒乓游戏机的甲乙双方各在不同的位置发球或击球。
(2)乒乓球的位置和移动方向由灯亮及依次点燃的方向决定,球移动的速度为0.1~1s移动一位。游戏者根据球的位置发出相应的动作,提前击球或出界均判失分。
(3)比赛用11分为一局来进行,甲乙双方都应设置各自的记分牌,任何一方先记满11分,该方就算胜了此局。当记分牌清零后,又可开始新的一局比赛。
1.3.2 设计方法
本设计是基于单片机的乒乓游戏机设计,分别进行了硬件和软件两部分的设计。硬件设计包括单片机电路、译码电路、发光二极管电路、按键电路、显示电路等电路的设计。软件设计是使用Keil uVision4软件编写与硬件模块相应的源程序。利用Proteus软件对电路进行仿真,最后通过制作实物实现设计。
2 乒乓游戏机设计方案
目前,有两种方案来设计乒乓游戏机设计。方案一是基于单片机的乒乓游戏机设计。方案二是基于FPGA的乒乓游戏机设计。
2.1 基于单片机的乒乓游戏机设计
方案一是基于单片机的乒乓游戏机设计,结果用LCD1602显示屏显示。软件方面,使用Keil uVision4进行编程。硬件设计包含单片机电路、模拟球台电路、按键电路、显示电路等电路的设计。软件设计包括:主程序、按键组程序(球拍模拟和暂停/开始子程序)、发球程序、线路程序(包括线路选择和LED点阵子程序)、回球程序、LCD显示程序。基于单片机的乒乓游戏机系统框图如图2.1所示。
单 片 机 模 块
电源电路
模拟球台电路
时钟电路
复位电路
LCD显示屏
按键电路
图2.1 基于单片机的乒乓游戏机的系统框图
2.1.1 硬件设计
电源电路设计:单片机正常工作电压为+5V,设计采用三端稳压集成电路输出+5V电压。
时钟电路设计:单片机可以看成是在时钟驱动下的时序逻辑电路,即单片机必须在时钟的驱动下才能工作。因此,单片机需要时钟电路支持,否则不能执行程序。
复位电路设计:单片机的复位电路使系统的所有功能部件都处于一个确定的初始状态,防止单片机执行错误操作、发出错误的指令等失误。单片机的复位方式有:手动按钮复位和上电复位。本设计采用手动按钮复位方式进行复位。
按键电路设计:包含两个按键组,一个是模拟球拍按键电路,一个是暂停/开始
和复位按键电路。模拟球拍按键分为左右两边,左右各四个。这四个按键其中三个是对LED点阵线路的操作,一个是进行加速;暂停/开始和复位按键是在运行任一程序时,对游戏机进行暂停或开始或复位。
模拟球台设计:包括译码电路设计和发光二极管设计。译码电路设计:本设计中采用16个发光二极管,而单片机的端口较少,因此采用3-8译码器节约端口。发光二极管设计:由单片机控制74LS138译码器,74LS138译码器译码控制LED点阵得点亮顺序和相应点亮时间。
显示电路设计:设计中采用LCD显示屏显示结果,左右两边分别用A、B表示。
2.1.2 软件设计
主程序:对乒乓游戏机进行初始化,定时器设置,对LED点阵输入数据等,延时扫描按键。
按键程序:在回球和发球时,按键按下给单片机传入数据作出相应处理。包括暂停/开始子程序,对系统进行暂停和开始。
发球程序:绿色指示灯亮起时,B得到发球球权,否则A得到发球球权。
线路程序:游戏发球有8个线路选择,AB分别4个线路选择,共有16个回球线路,存在数组b[16]中,包括LED点阵子程序,由单片机线路和delay_1(t)控制74LS138译码器,74LS138译码器译码控制LED点阵得点亮顺序和相应点亮时间。
回球程序:当球在A边时,A可在相应delay_1(t)中感应A按键组的数据并作出相应处理;当球在B边时,同理。
显示程序:显示游戏比分,当A或B到达11分时进入相应win子程序。
2.2 基于FPGA的乒乓游戏机设计
方案二是基于FPGA的乒乓游戏机设计。因为学校具备专门的实验箱,如果采用方案二只需编程便可实现。通过对各部分编写VHDL程序,然后进行编译、仿真、逻辑综合、逻辑适配,最后进行编程下载,并通过程序验证结果。用16个发光二极管代表乒乓球,在游戏机的两侧各设置两个开关,一个是发球开关,一个是击球开关。甲方按动发球开关时,靠近甲方的第一盏灯亮,然后发光二极管由甲向乙依次点亮,代表乒乓球在移动。当球过网后,按设计者规定的球位乙方就可以击球。若乙方提前击球或没有击到球,则判乙方失分,甲方自动加分,重新发球比赛继续进行到一方记分到11分,该局结束,记分牌清零,可以开始新的一局比赛。其系统框图如2.2所示。
图2.2 基于FPGA乒乓游戏机的系统框图
2.3 方案比较与选择
FPGA的运行速度很快,适合高速场合,而单片机的运行速度低的多;FPGA的I/O口多,容易实现大规模系统,方便连接外设,而单片机的I/O口较少,适合小规模系统;FPGA的内部程序是并行运行,具有处理复杂功能的能力,而单片机程序时串行
执行,程序需要执行完一条才能执行下一条,处理突发事件时只能调用中断资源;FPGA包含单片机和DSP软核,即单片机和DSP能实现的功能,FPGA一般都能实现。单片机设计属于软件范畴,它的硬件即单片机芯片是固定的,通过软件编程语言描述在硬件芯片上的执行的软件指令。FPGA设计属于硬件范畴,它的硬件即FPGA是可编程的,是一个通过硬件描述语言在FPGA芯片上自定义集成电路的过程。
由上可知,FPGA具有很多优点,但是对本设计而言是大材小用,而且芯片造价较高,因此选用单片机完成本设计。
在国内,有很多成熟且性价比高的单片机,以51单片机为主。本设计对芯片的要求不高,因此选用性价比高的单片机STCC51。STCC51是ISP的系统可编程芯片,可以直接将程序烧录到芯片中,方便程序的修改和实物调试。其工作电压要求低,工作频率可达48MHz。并且可通过串口直接下载程序,数秒即可完成下载。采用单片机完成设计,可利用Proteus绘制电路原理图,用Keil uVision4进行编程,然后进行仿真调试,减少出错。并且采用C语言编程,移植性强,使端口的程序控制变得简单。
综上所述,采用方案一完成乒乓游戏机的设计。
3硬件电路的设计
3.1 硬件核心电路选择
乒乓游戏机设计选用单片机作为主控芯片,设计选用性价比高的STCC51单片机。STCC51与其它51单片机比较,具有成本低,性能好的优点,并且其具有在线编程功能,可以直接将程序烧录到芯片中,不需要对硬件进行修改。就乒乓游戏机而言,STCC51能通过程序的编写实现所需的功能。
3.1.1 单片机STCC51简介
单片机STCC51是宏晶科技推出的超强抗干扰/低功耗的单片机,指令代码与引脚结构完全兼容传统的8051单片机。其最高工作时钟频率为80MHz,片内含8K Bytes的可反复擦写1000次的Flash ROM,芯片内集成了通用8位处理器和ISP Flash存储单元,具有在系统可编程特性,配合PC端的控制程序即可将用户的程序代码下载到单片机内部,并且速度更快。
STCC51的芯片擦除特性:整个PEROM阵列与三个锁定位的电擦除可通过正确的控制信号组合,并保持ALE管脚低电平10ms来完成。在芯片擦除中,代码阵列全被写“1”,且在任何非空存储字节被重复编程以前,必须执行该操作。STCC51芯片及其引脚如图3.1所示。
图3.1 STCC51芯片及其芯片引脚图
3.1.2 单片机端口分配
乒乓游戏机需要八个端口接按键;16个发光二极管则通过两个3-8译码器与单片机连接,需要六个端口;LCD显示屏需要7个端口;单片机时钟电路接两个端口;复位电路接复位端口;暂停/开始按键需要两个端口;发球指示灯和暂停指示灯需要两个端口。下面对所需端口进行介绍及分配:
P0口(39~32脚):P0.0~P0.7统称为P0口。P0口是一个三态双向口,每个引脚可吸收八个TTL门电流。当P0口的管脚第一次写“1”时,被定义为高阻输入。P0可用于外部程序数据存储器,它可以被定义为数据/地址的低八位。在Flash编程时,P0口用作原码输入口。当Flash进行校验时,P0输出原码,必须接上拉电阻。
P1口(1~8脚):P1.0~P1.7统称为P1口.P1口为准双向口,P1口缓冲器能接收四个TTL门电流。P1口的管脚写“1”后,内部上拉为高,可用作输入。P1口被外部下拉为低电平时,因为内部上拉,将输出电流。在Flash编程和校验时,P1口接收低八位地址。
P2口(21~28脚):P2.0~P2.7统称为P2口。P2口为准双向口,缓冲器可接收/输出4个TTL门电流。当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。作为输入时,P2口的管脚被外部拉低,因为内部上拉将输出电流。当P2口用于外部程序存储器或十六位地址外部数据存储器进行存取时,P2口输出高八位地址。在给出地址“1”时,利用上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出单片机特殊功能寄存器的内容。P2口在Flash编程和校验时接收高八位地址信号和控制信号。
P3口(10~17脚):P3.0~P3.7统称为P3口。P2口为准,双向口可接收/输出四个TTL门电流。当P3口写入“1”时,被内部上拉为高电平,并用作输入。当外部下拉为低电平,因为上拉的缘故,P3口将输出电流。
P3口作为第二功能使用时各端口引脚的作用,如表3.1所示。
表3.1 P3口的第二功能
| 端口引脚 | 第二功能 |
| 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 (外部数据存储器读选通) |
RST:复位输入。振荡器复位器件时,保持RST引脚两个机器周期高电平时间。
XTAL1:反向放大器的输入、内部时钟工作电路的输入。
XTAL2:反向振荡器的输出。
本设计中,STCC51单片机的管脚如下分配:P0.0~P0.7口用作按键输入口,接上拉电阻;P1.0~P1.1口作为暂停、开始按键输入口;P1.2~P1.5作为LCD显示屏输入口;P1.6作为发球权指示灯,P1.7作为暂停指示灯控制口;P2.0~P2.7作为译码器信号输入口控制发光二极管;P3.2~P3.4作为LCD显示屏的控制端;RST引脚为复位电路输入口;XTAL1、XTAL2分别作为片内振荡器的输入和输出。
3.2 电源电路的设计
单片机STCC51的工作电压为+5V,因此需要一个电源电路来提供这一电压。设计通过固定三端稳压集器,输出使单片机工作的+5V电压。
固定三端稳压器主要有78XX系列的正电压输出稳压器和79XX系列的负电压稳压器。两个系列的固定三端稳压器,输出电压有5V、6V、9V、12V、15V、18V、24V等规格,最大输出电流为1.5A。这种三端稳压器内部包含了过流、过热和调整管的保护电路,使用时组成稳压电源所需的外围元件少,使用起来可靠、方便、快捷。
7805的参数为:在25℃,输入电压为7.5~20V时,输出电压为4.8V~5.2V。因此本设计采用三端稳压器7805输出5V电压。固定三端稳压器7805的1脚为输入端,2脚为接地端,三脚为输出端。芯片7805及其引脚图如图3.2所示。
图3.2 芯片7805及其引脚图
3.3 时钟电路的设计
单片机,可以认为是在时钟驱动下的时序逻辑电路,即单片机必须在时钟的驱动下才能够工作。单片机内部含有一个可以构成振荡器的放大电路。在单片机内部含时钟振荡电路,外部一个振荡源产生是送到单片机内部,决定单片机的工作速度。此设计选用内部振荡方式,即把放大器与振荡器连接,构成的内部自激振荡器并产生振荡时钟脉冲。选用的元器件为一个12MHz的石英晶体振荡器,两个30pF的电容。此电路在加点延迟10ms后振荡起振,在XTAL2引脚产生正弦时钟信号。电路中的电容作用有两个:一是对振荡器的频率进行微调,二是帮助振荡器起振。
因为石英晶体振荡器的振荡频率为12MHz,即单片机的振荡周期为1us,状态周期为2us,机器周期为12us。时钟电路设计如图3.3所示。
图3.3 时钟电路图
3.4 复位电路的设计
单片机STCC51第九引脚为硬件复位端。对该引脚程序4个机器周期的高电平即可实现复位,复位后单片机都恢复到初始化状态。复位电路由按键及电容,电阻构成。当按下按键时,电源经电阻R1、R2分压,在复位管脚产生一个复位高电平,此时单片机处于复位状态。当上电后,电容缓慢充电,单片机的复位管脚电压由高向低转化,经过一定时间,复位管脚处于稳定的低电平状态,此时单片机复位完毕,系统从0000H执行程序。该电路使用了按键一个,10uF的电容一个,10KΩ和1kΩ的电阻各一个。复位电路设计图如图3.4所示。
图3.4复位电路设计图
3.5 按键电路的设计
按键是一种常见的控制电器元件,常用来接通或断开控制电路,从而达到控制电路的一种开关。按键共有4个引脚,当未按下按键时,2引脚和3引脚是导通的,1引脚和4引脚是导通的。当按下按键时,1引脚和2引脚连通,3引脚和4引脚连通,
2引脚和3引脚连通,1引脚和4引脚连通。按键及其引脚图如图3.5所示。
图3.5按键及其引脚图
乒乓游戏机的按键电路包含两个按键组,一个是模拟球拍按键电路,一个是暂停/开始和复位按键电路。模拟球拍按键分为左右两边,左右各四个。这四个按键其中三个是对LED点阵线路的操作,一个是进行加速;暂停/开始和复位按键是在运行任一程序时,对游戏机进行暂停或开始或复位。
设计中模拟球拍按键与P0口相连,同时P0口接5KΩ的上拉电阻。当发光二极管亮时,按下按键进行控制。当按键按下的时候,相应端口感应输入为低电平0。模拟球拍按键电路设计图如3.6所示。
图3.6 按键电路设计图
暂停和开始按键分别与单片机的P1.0和P1.1相连。复位按键与单片机复位端口相连。暂停和开始按键电路设计图如图3.7所示。
图3.7 暂停和开始按键电路设计图
3.6 模拟球台电路的设计
模拟球台电路设计包括译码电路设计和发光二极管设计。乒乓游戏机采用16个发光二极管,单片机的端口有限,因此采用单片机的P2口的5个端口控制74LS138译码器进行译码,节约端口。译码器74LS138的输入电压范围为+3.5~+5V。
3.6.1译码器简介
本设计采用74LS138译码器进行译码。74LS138为3-8线译码器,其中LS指采用低功耗肖特基电路。该译码器有3位二进制输入A0、A1、A2,共有8种状态的组合,即可译出8个输出信号Y0~Y7,输出低电平有效。此外,还设置了E1、E2和E3三个使能输入端,为电路功能的扩展提供方便。译码器74LS138的管脚及其功能如表3.2所示。
表3.2 译码器74LS138管脚功能
| 管脚 | 功能 |
| VCC | 电源正 |
| GND | 地 |
| E1 | 选通端 |
| E2 /E3 | 选通端(低电平有效) |
| A0~A3 | 地址输入端 |
| Y0~Y7: | 输出端(低电平有效) |
当一个选通端(E1)为高电平,另两个选通端(E2)和 (E3)为低电平时,可将地址端(A0、A1、A2)的二进制编码在对应的输出端以低电平译出。
74LS138的引脚图如图3.8示。
图3.8 74LS138的引脚图
74LS138的功能真值表如表3.3所示。
表3.3 74LS138功能真值表
| 输 | 入 | 输 | 出 | ||||||||||
| E3 | E2 | E1 | A2 | A1 | A0 | Y0 | Y1 | Y2 | Y3 | Y4 | Y5 | Y6 | Y7 |
| X | H | X | X | X | X | H | H | H | H | H | H | H | H |
| X | X | H | X | X | X | H | H | H | H | H | H | H | H |
| L | X | X | X | X | X | H | H | H | H | H | H | H | H |
| H | L | L | L | L | L | L | H | H | H | H | H | H | H |
| H | L | L | L | L | H | H | L | H | H | H | H | H | H |
| H | L | L | L | H | L | H | H | L | H | H | H | H | H |
| H | L | L | L | H | H | H | H | H | L | H | H | H | H |
| H | L | L | H | L | L | H | H | H | H | L | H | H | H |
| H | L | L | H | L | H | H | H | H | H | H | L | H | H |
| H | L | L | H | H | L | H | H | H | H | H | H | L | H |
| H | L | L | H | H | H | H | H | H | H | H | H | H | L |
发光二极管简称为LED,是一种能发光的半导体电子元件。这种电子元件在1962年出现,由镓(Ga)与砷(As)、磷(P)的化合物组成的二极管,电子与空穴复合时能辐射出可见光。其中,磷砷化镓二极管发红光,磷化镓二极管发绿光,碳化硅二极管发黄光。发光二极管具有单向导通性,即发光二极管只能往一个方向通电,这种特性叫做正向偏置(正向偏压)。
发光二极管的基本结构是一块电致发光的半导体材料,置于一个有引线的架子上,然后用环氧树脂密封,起到保护内部芯片线的作用。发光二极管的核心部分是由P型半导体和N型半导体组成的晶片,在P型半导体和N型半导体之间有一个过渡层,称为PN结。在某些半导体材料的PN结中,注入少数载流子与多数数载流子复合时把多余的能量以光的形式释放出来,从而把电能转换成光能。发光二极管的两根引线较长的一根是正极,需接电源正极。发光二极管及其构造如图3.9所示。
图3.9发光二极管及其构造
3.6.3 模拟球拍电路的设计
单片机P2.0~P2.3控制两个译码器的A,B,C端,P2.4和P2.7分别控制两个译码器的E1端,且E2、E3两个端口接地。单片机P2口输出信号,从而达到控制发光二极管的熄灭与点亮。其电路图如图3.10所示。
图3.10模拟球台电路设计图
3.7 显示电路的设计
乒乓游戏机的数据较为简单,只需要显示比分和最终胜利的状态,因此选用只显示字符和数字的LCD1602显示屏。
3.7.1 LCD1602简介
乒乓游戏机显示电路设计采用LCD1602显示屏。LCD1602为工业字符型液晶,能够同时显示32个字符。它是专门用来显示字母、数字、符号等的点阵型液晶模块。由若干个5*7或5*11等点阵字符位组成。每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用。LCD采用标准的16脚接口,其管脚功能如表3.4所示。
表3.4 LCD1602的管脚功能表
| 管脚 | 功能 |
| VSS | 电源地 |
| VCC | 接5V电源电极 |
| V0(VEE) | 液晶显示器对比度调整端,接正电源对比度最弱,接地电源最高 |
| RS | 寄存器选择。高电平时选择数据寄存器,低电平时选择指令寄存器 |
| RW | 读写信号线。高电平时读取信息,低电平时进行写操作 |
| E(EN) | 使能端。高电平时读取信息,负跳变时执行指令 |
| D0~D7 | 8位双向数据端 |
| BLA | 背光正极 |
| BLK | 背光负极 |
LCD1602及其引脚图如图3.11所示。
图3.11 LCD1602及其引脚图
3.7.2 显示电路的设计
此设计中的显示模块采用LCD来显示乒乓游戏机的AB队比分。LCD1602的D4、D5、D6、D7分别与单片机中的P1.5、P1.4、P1.3、P1.2相连,用于数据和地址的传输。LCD1602的RS、RW、E分别与单片机中的P3.4、P3.3、P3.2相连,用于写入控制。其电路设计图如图3.12所示。
图3.12显示电路设计图
3.8 乒乓游戏机总电路的设计
本设计采用Proteus绘制电路设计仿真图,乒乓游戏机的硬件设计包括单片机电路、译码电路、发光二极管电路、按键电路、显示电路等电路的设计。其仿真图如图3.13所示。
图3.13总电路设计图
乒乓游戏机的硬件包括单片机电路、译码电路、发光二极管电路、按键电路、显示电路等电路。其中单片机电路包括:晶振电路,复位电路;由译码器接P2的5个I/O口控制16个模拟乒乓球台桌LED灯;由单片机的P0口接上拉电阻,感应按键电路的输入;有P1.2到P1.5给LCD进行数据的输入,P3.2-P3.3给LCD进行写入控制。
4 乒乓游戏机的软件设计及编程
本系统的软件主要采用模块化结构设计,具体的程序有主程序、按键组程序(球拍模拟和暂停/开始子程序)、发球程序、线路程序(包括线路选择和LED点阵子程序)、回球程序、LCD显示程序。系统流程图如图4.1所示。
图4.1 系统流程图
通过程序实现的功能为:在主程序进入初始化,LCD屏的清零,及初始化显示设置;然后进入发球程序,绿色指示灯亮起时,B得到球权,否则A得到球权;当发球成功后,进入线路模块,在不同的情况进入相应的线路,依据线路的选择依次点亮线路所包含的LED灯;而后进入回球程序,回球成功继续进入线路程序,回球失败,对手分数加1,并进入LCD显示程序;当AB队 任一队11分后进入相应win子程序。暂停/开始程序在定时扫描,当暂停键按下时,游戏暂停,在游戏暂停时当开始按下游戏继续。
4.1 主程序的设计及功能实现
主程序的功能是进行初始化工作,并控制“乒乓球”游戏的开始。LED灯组接单片机的P2口上,按键组接单片机P0口上,LCD显示屏由单片机控制。游戏开始时,程序控制显示上行A:0;下行B:0。
void main()
{
write_com(0x01);//显示器清屏
P2=0;//LED点阵全部熄灭
fuwei();//数据初始化
EA=1;
EX0=1;
EX1=1;
ET0=1;
IT0=1;
IT1=1;
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;//定式扫描初始化设置
qiuquan(); //跳转到发球程序
while(1)//循环扫描并点亮相应LED
{
int t=1000+w*1000;
P2=q[n];
delay_1(t);//延时处理程序
xianlu();//线路控制程序
}
}
4.2 按键组的设计及功能实现
此程序贯穿了整个系统框图中,包括球拍模拟子程序和暂停/开始子程序。
4.2.1 球拍模拟子程序
单片机P0口在相应时间段内感应来自由按键组传来的数据,如果在delay_1(t)中作出正确的选择,进入回球程序,否则对方加1分。
图4.2 按键组流程图
4.2.2 暂停/开始子程序
当暂停键被按下后,程序进入中断,暂停灯亮起,当按下开始按键时,程序继续。其流程图如图4.3所示。
图4.3 暂停/开始程序流程图
4.3 发球程序的设计及功能实现
绿色指示灯亮起时,B得到发球球权,否则A得到发球球权。
void qiuquan(void)
{
w=1;//球速控制变量
v=0;//发球控制变量
if(f>=3)//球权控制变量0-3循环。
f=0;
else
f++;
if(f<2)//当f小于2时A得到球权
Ajiqiu();
else//当f大于2时B得到球权
Bjiqiu();
}
4.4 线路程序的设计及功能实现
线路程序包括线路选择子程序和LED点阵子程序。
4.4.1 线路选择子程序
游戏发球有8个线路选择,AB分别4个线路选择,发球的4个选择由线路b[16]和初始点亮灯一起组成。回球总的线路有16个,存在数组b[16]中。
void xianlu(void)//线路程序按顺序给LED点阵输入相应数据
{
if(m>256)//m取自b[]中得数据
{n=m/256;m=m%256;}
else if(m>16)
{n=m/16;m=m%16;}
else if(m<16&&m>=0)
{n=m;m=-1;}
else if(m<0)//当m取完数据时,按键都没做出正确输入时,表明A或B回球失败。
{
P2=0;
if(n<8)
chang3();
else if(n>=8)
chang1();
qiuquan(); }
}
4.4.2 LED点阵子程序
由单片机线路和delay_1(t)控制74LS138译码器,74LS138译码器译码控制LED点阵得点亮顺序和相应点亮时间。q[16]寄存数组,列如P2=q[0]时点亮A边的第一个灯,单片机将数据传输给74LS138进行译码点亮相应的LED实现乒乓球的移动。
4.5 回球程序的设计及功能实现
当球在A边时,A可在相应delay_1(t)中感应A按键组的数据并作出相应处理;当球在B边时,同理。这里需要对16个灯(D2-D17)进行处理。下面对其中一个灯进行解释。
w=P0_3;//A的P0_3控制游戏的速度
//D2
if(n==0)//n==0时D2灯点亮
{
if(x==13&&!P0_0)//当线路为13时且P0_0按下时按以下处理。
{
if(!w)
x=3;
else
x=0;
while(!P0_0) ;
m=b[x];
}
if(x==8)//当线路为8时只能按以下处理
{
if(!P0_0)
{ x=3;
while(!P0_0);
m=b[x];}
else if(!P0_1)
{ x=0;
while(!P0_1);
m=b[x];}
}
}
4.6 LCD显示程序设计及功能实现
LCD1602与单片机P1口相连,程序控制显示上行A:0;下行B:0。当A或B到达11分时进入相应win子程序。
write_com(0x80+2);//第一行隔两位写入以下字符‘A’‘:’‘ ’‘0’;
write_data('A');
write_data(':');
write_data(' ');
write_data('0');
write_com(0xC0+2);//第一行隔两位写入以下字符‘B’‘:’‘ ’‘0’;
write_data('B');
write_data(':');
write_data(' ');
write_data('0');
4.7 设计源程序
设计源程序见附录1。
5 系统调试及分析
5.1 仿真调试及分析
乒乓游戏机设计利用Proteus软件设计原理图,Keil uVision4软件进行编程。
5.1.1 Proteus软件简介
Proteus软件是英国Labcenter electronics公司出版的EDA工具软件。它不仅具有EDA工具软件的仿真功能,还能仿真单片机及外围器件。从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换至PCB设计,实现了从概念到产品的完整设计。其处理器支持的模型有:8051、HC11、PIC10/12/16/18/24/30/D是、PIC33、AVR、ARM、8086和MSP430等。在编译方面,它也支持IAR、Keil和MPLAB等多种编译器。
电路原理图是生产电子产品的基础,电路设计的最终目的是从电路原理图到设计出印制电路板图,经过焊接、组装、调试得到合格的电子产品。利用Proteus绘制原理图的基本流程如图5.1所示。
图5.1 绘制原理图的基本流程
5.1.2 Keil uVision4软件简介
Keil uVision4是德国Keil Software公司出品的51系列兼容单片机C语言软件开发系统。KEILC51标准C编译器为8051微控制器的软件提供了C语言环境,同时保留了汇编代码高效、快速的特点。它比以前的Keil uVision系列的优点是引入灵活的窗口管理系统。目前使用Keil uVision4的产品有Keil MDK-ARM,Keil C51,Keil C166和Keil C251。
5.1.3 仿真调试
仿真调试的步骤:
(1)在Keil中建立工程,输入程序,进行编译,修改直至无错,最后编译并保存。将保存的程序进行编译和生成.hex文件,如图5.2所示。
图 5.2 生成.hex文件
(2)在Proteus中设计硬件原理图。
(3)在Proteus中导入.hex文件,如图5.3所示。导入的方法:将鼠标置于电路图中STCC51器件上,先右击再左击,即弹出导入框,再导入框中导入乒乓球.hex文件。
图5.3 导入 乒乓球.hex文件
(4)点击仿真盘框中的运行按钮,电路进入仿真状态,开始调试。如图5.4所示。
图5.4仿真调试图
在调试过程中,观看LCD显示屏的变化,由此得出设计是否正确。如果不正确,按以上步骤进行修改,直到达到设计要求。
5.1.4 仿真调试的结果分析
对电路进行仿真调试后,发现了一些问题。
(1)LED未按正常预期工作,发球与回球的程序存在共同部分,加入发球控制参数后,正常工作。
(2)发球程序出现问题,有时候发球指示灯亮时,B却不能成功发球,经过修改程序,解决这个问题。
5.2 实物调试及分析
5.2.1 制作实物的过程
根据原理图焊接电路。在每焊接完成一个模块时,检查电路焊接是否正确、是否连错端口、是否有虚焊,确认无误后,完成焊接。如图5.5所示。
焊接遇到的问题:
(1)LED灯接反,导致LED点阵不工作,改正全部的点阵灯后,正常工作。
(2)74LS138没有接电源,开始一直不工作,改正后正常工作。
5.2.2 进行实物调试
用烧录器将Keil软件中生成的.hex文件烧录到单片机STCC51芯片中。烧录的步骤为:选项/串口设置、芯片型号选择STCC51RC、打开程序文件、选择.hex文件、Download/下载、擦除、查空、编程、校验。烧录程序图如图5.6所示。
5.6 烧录程序图
最后将芯片安装到硬件电路中,接入5V稳压电源,乒乓游戏机开始运行。调试初始状态如图5.7所示。
图5.7 调试初始状态
AB双方任一方为11分时,结束游戏,11分的一方获得胜利。游戏胜利状态图如图5.8所示。
图5.8 游戏状态胜利图
按下暂停键,游戏机暂停,同时暂停指示灯亮。暂停调试状态图如图5.9所示。
图5.9 暂停调试状态图
5.2.3 实物调试的结果分析
完成实物制作后,对总电路进行调试。在调试中遇到的问题:
(1)在按键操作过程中,发光二极管快速变化,与设定值不一样。经分析,原因为程序中的防抖动功能不完善。在实际的电路中,机械式按键按下或释放时,因为机械弹性作用的影响,通常伴随有一定时间的触点机械抖动,然后其触点才稳定下来。可能在按下按键时,已经对按键进行了几次操作,因此发光二极管快速的变化。通过对程序的修改,问题解决。
(2)发光二极管未按预期效果被点亮,经过分析,发现实际中与仿真的接线不同,改正相应参数后,正常运行。
6 结论与展望
6.1 结论
本设计根据乒乓游戏机的功能要求,本设计采用性价比高的单片机设计出操作方便,系统稳定度高的乒乓游戏机设计。
本设计采用单片机STCC51作为主控芯片,采用Proteus软件和Keil uVision4软件分别进行硬件仿真和软件编程,最后制作实物,实现乒乓游戏机的双人对打。本设计采用4×4的线路电路,乒乓球的位置和移动方向由灯亮及依次灯亮的方向决定使用,乒乓游戏机的A、B两方在各自不同的位置发球或击球,分别有左、中、右、加速四个按键作为模拟球拍。游戏者根据球的位置按下相应的按键得分,最后通过LCD显示屏显示数据。
通过一系列的仿真调试和实物调试,已验证本设计的开发方案是基本可行的。这种成本低,操作方便,稳定度高的设计,能很好的适应乒乓游戏机的开发。
此外,本次设计还有以下一些可以加以改进的地方:
(1)设计线路复杂,如果可以采取无线的方式,则更加方便携带与玩耍。
(2)选用更加好的LCD显示屏,使界面更加美观
(3)娱乐效果过低,如果可以玩游戏的同时播放音乐,或动态显示,则提高娱乐性。
6.2 展望
如今各种不同类型的游戏设备一直是消费领域的热点,作为电子游戏产品,乒乓游戏机的竞争十分激烈。在功能上,乒乓游戏机不应只是一个益智,还可以提供娱乐性,提供锻炼身体的功能,比如游戏时添加音乐,采用人体感应技术实现人机互动,采用3D效果更加真实。让人感觉不枯燥,且具有丰富的娱乐性。这些都将使乒乓游戏机更加成熟,更受欢迎。
谢辞(Acknowledge)
转眼间,两个月过去了。在实验室的两个月里,我完成了毕业设计。让我完整的完成了一次电子产品的生产,经过了设计、生产、安装、调试等一系列的过程。
回顾四年大学生活,有太多事情对以后的人生影响深远。特别是2012年暑假,我在实验室学到了很多,对我这次的毕业设计的完成提供了基础。
感谢我的指导老师孙晓玲老师。她在忙碌的教学工作中,孙老师每周二都会对我们的毕业设计审查,从设计的选题直至最后毕业论文的修改整个过程,孙老师都给出了自己的宝贵意见,孙老师的悉心指导和建议给了我极大的帮助,在此对孙老师表示衷心感谢。同时感谢所有教过我的老师,谢谢你们对我们孜孜不悔的教诲,你们传授的知识为我在以后的道路奠定了良好的基础。
在此之外感谢学校,给我们一个良好的学习环境,提供我们毕业设计所需的器材,让我们能够更方便的进行毕业设计。感谢实验室的同学,在我的设计出现问题时,提出意见,在进行自己的毕业设计时愿意挤出时间帮助我。感谢同学们让我拥有了美好的四年大学生活。
参考文献
[1]谢龙汉 莫衍.Proteus电子电路设计及仿真.北京:电子工业出版社,2012
[2]周灵彬 任开杰.基于Proteus 的电路与PCB的设计.北京:电子工业出版社,2010
[3]康华光.电子技术基础模拟部分(第五版). 北京:高等教育出版社,2006.1
[4]康华光.电子技术基础数字部分(第五版).北京:高等教育出版社,2006.1
[5]李建忠.单片机原理及应用(第二版).西安:西安电子科技大学出版社,2008.2
[6]郝建国 郑燕 薛延侠.单片机在电子电路设计中的应用.北京:清华大学出版社,2006.5
[7]顾三春 仝迪.电子技术实验.北京:化学工业出版社,2009.8
[8]赵广林.常用电子元器件识别/检测/选用一读通.北京:电子工业出版社,2007.4
[9]米旭.Protel 2004电路设计与仿真.北京:机械工业出版社,2006.1
[10]王国胜.C#基础与案件开发祥解.清华大学出版社,2009
[11]周长发. C#面向对象编程.电子工业出版社,2007
[12]谢自美.电子线路综合设计.武汉:华中科技大学出版社,2006.6
[13]彭伟.单片机C语言程序设计实训100例:基于8051+Proteus仿真.北京:电子工业出版社,2009
[14]刘同法.单片机C语言编程基础与实践.北京:北京航空航天大学出版社,2009
[15]沈长生.常用电子元器件使用一读通.北京:人民邮电出版社,2002.4
[16]江国强 蒋艳红.现代数字逻辑电路实验指导.北京:电子工业出版社,2003.8
附录1:程序
#include #include"lcd1602.h" sbit P1_7=P1^7; sbit P1_6=P1^6; sbit P1_0=P1^0; sbit P1_1=P1^1; sbit P0_0=P0^0; sbit P0_1=P0^1; sbit P0_2=P0^2; sbit P0_3=P0^3; sbit P0_4=P0^4; sbit P0_5=P0^5; sbit P0_6=P0^6; sbit P0_7=P0^7; void delay(int q); void chang0(void); void chang1(void); void chang2(void); void chang3(void); void chang4(void); void qiuquan(void); void Ajiqiu(void); void Bjiqiu(void); void xianlu(void); void huiqiu(void); void Ahuiqiu(void); void Bhuiqiu(void); void Awin(void); void Bwin(void); void fuwei(void); void delay_1(int t); int a[10]={0,1,2,3,4,5,6,7,8,9}; //int q[16]={11,10,9,8,12,13,14,15,131,130,129,128,132,133,134,135};//仿真 int q[16]={9,13,11,15,8,12,10,14,129,133,131,135,128,132,130,134}; //实际 int b[16]={11,1182,1437,1455,1710,1692,1983,1965,2112,2130,2385,2403,2658,20,2931,2913}; int i1=0,i2=0,i3=0,i4=0,i=20,k=4,n=0,w=1,t,f=-1,x,m,s1,c1,s2,c2,v; void main() { write_com(0x01); P2=0; fuwei(); EA=1; EX0=1; EX1=1; ET0=1; IT0=1; IT1=1; TMOD=0X01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; TR0=1; qiuquan(); while(1) { int t=1000+w*1000; P2=q[n]; delay_1(t); xianlu(); } } void ex0(void) interrupt 0 { } void it0(void) interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; i--; if(P1_0==0) { while(P1_0==0); chang0(); i=20; } c1=P0_0&&P0_1&&P0_2; c2=P0_4&&P0_5&&P0_6; if(n<8&&!c1&&v) Ahuiqiu(); else if(n>=8&&!c2&&v) Bhuiqiu(); } //暂停模块 void ex1(void)interrupt 2 { if(P1_1==0) { P1_7=1; chang0(); } } void chang0(void) { P1_7=1; while(1) { if(P1_1==0) { P1_7=0; return; } } } //回球模块 void delay_1(int t) { int z; for(;t>0;t--) for(z=50;z>0;z--) { } } //A回球 void Ahuiqiu(void) {w=P0_3; //D2 if(n==0) { if(x==13&&!P0_0) { if(!w) x=3; else x=0; while(!P0_0) ; m=b[x]; } if(x==8) { if(!P0_0) { x=3; while(!P0_0); m=b[x];} else if(!P0_1) { x=0; while(!P0_1); m=b[x];} } } //D3 else if(n==1) { if(x==10&&!P0_1) { x=2; while(!P0_1) ; m=b[x]; } else if(x==15&&!P0_0) { x=2; while(!P0_1); m=b[x]; } } //D4 else if(n==2) { if(x==12&&!P0_1) { x=4; while(P0_1); m=b[x]; } else if(x==9&&!P0_0) { if(!w) x=4; while(!P0_1); m=b[x]; } } //D5 else if(n==3) { if(x==11&&!P0_2) { if(!w) x=5; else x=6; while(!P0_2) ; m=b[x]; } else if(x==14) { if(!P0_2) { x=5; while(!P0_2); m=b[x];} else if(!P0_1) { x=6; while(!P0_1); m=b[x];} } } //D6 if(n==4) { if(x==8) { if(!P0_0) { x=1; while(!P0_0); m=b[x]%256;} else if(!P0_1) { x=0; while(!P0_1); m=b[x]%256;} } } //D7 else if(n==5) { if(x==10) { if(!P0_0) { x=3; while(!P0_0); m=b[x]%256;} else if(!P0_1) { x=2; while(!P0_1); m=b[x]%256;} } else if(x==13&&!P0_0) { x=2; while(!P0_0) ; m=b[x]%256; } } //D8 else if(n==6) { if(x==11&&!P0_2) { if(!w) x=5; else x=4; while(!P0_2) ; m=b[x]%256; } else if(x==12) { if(!P0_2) { x=5; while(!P0_2); m=b[x]%256;} else if(!P0_1) { x=4; while(!P0_1); m=b[x]%256;} } } //D9 if(n==7) { if(x==14) { if(!P0_2) { x=7; while(!P0_2); m=b[x]%256;} else if(!P0_1) { x=6; while(!P0_1); m=b[x]%256;} } } //else //chang3(); return; } //B回球 void Bhuiqiu(void) {w=P0_7; //D17 if(n==15) { if(x==3&&!P0_6) { if(!w) x=13; else x=14; while(!P0_6) ; m=b[x]; } if(x==6) { if(!P0_6) { x=13; while(!P0_6); m=b[x];} else if(!P0_5) { x=14; while(!P0_5); m=b[x];} } } //D16 else if(n==14) { if(x==4&&!P0_5) { x=12; while(!P0_5) ; m=b[x]; } else if(x==1&&!P0_6) { x=12; while(!P0_6); m=b[x]; } } //D15 else if(n==13) { if(x==2&&!P0_5) { x=10; while(P0_5); m=b[x]; } else if(x==5&&!P0_4) { x=10; while(!P0_4); m=b[x]; } } //D14 else if(n==12) { if(x==5&&!P0_4) { if(!w) x=11; else x=8; while(!P0_4) ; m=b[x]; } else if(x==0) { if(!P0_4) { x=11; while(!P0_4); m=b[x];} else if(!P0_5) { x=8; while(!P0_5); m=b[x];} } } //D13 if(n==11) { if(x==6) { if(!P0_6) { x=15; while(!P0_6); m=b[x]%256;} else if(!P0_5) { x=14; while(!P0_5); m=b[x]%236;} } } //D12 else if(n==10) { if(x==4) { if(!P0_6) { x=13; while(!P0_6); m=b[x]%256;} else if(!P0_5) { x=12; while(!P0_5); m=b[x]%256;} } else if(x==3&&!P0_6) { x=12; while(!P0_0) ; m=b[x]%256; } } //D11 else if(n==9) { if(x==5&&!P0_4) { x=10; while(!P0_4) ; m=b[x]%256; } else if(x==2) { if(!P0_4) { x=11; while(!P0_4); m=b[x]%256;} else if(!P0_5) { x=10; while(!P0_5); m=b[x]%256;} } } //D10 if(n==8) { if(x==0) { if(!P0_4) { x=9; while(!P0_4); m=b[x]%256;} else if(!P0_5) { x=8; while(!P0_5); m=b[x]%256;} } } return; } //发球模块 void qiuquan(void) { w=1; v=0; if(f>=3) f=0; else f++; if(f<2) Ajiqiu(); else Bjiqiu(); } void Ajiqiu(void) { while(1) { s1=P0_0&&P0_1&&P0_2&&P0_3; if(s1!=1) { delay(10); if(P0_0==0) {n=0;x=3;m=b[x];while(!P0_0);} else if(P0_1==0) {n=1;x=2;m=b[x];while(!P0_1);} else if(P0_2==0) {n=3;x=5;m=b[x];while(!P0_2);} else if(P0_3==0) {n=2;x=4;m=b[x];while(!P0_3);} delay(10); v=1; return; } } } void Bjiqiu(void) { P1_6=1; while(1) { s2=P0_4&&P0_5&&P0_6&&P0_7; if(s2!=1) { delay(10); if(P0_4==0) {n=12;x=11;m=b[x];while(!P0_4);} else if(P0_5==0) {n=14;x=12;m=b[x];while(!P0_5);} else if(P0_6==0) {n=15;x=13;m=b[x];while(!P0_6);} else if(P0_7==0) {n=13;x=10;m=b[x];while(!P0_7);} delay(10); v=1; P1_6=0; return; } } } //线路控制 void xianlu(void) { if(m>256) {n=m/256;m=m%256;} else if(m>16) {n=m/16;m=m%16;} else if(m<16&&m>=0) {n=m;m=-1;} else if(m<0) { P2=0; if(n<8) chang3(); else if(n>=8) chang1(); qiuquan(); } } //显示模块 void chang1(void) { i1++; if(i1==0) {write_com(0x80+6);write_data('0');chang2();} else if(i1==1) {write_com(0x80+6);write_data('1'); } else if(i1==2) {write_com(0x80+6);write_data('2'); } else if(i1==3) {write_com(0x80+6);write_data('3'); } else if(i1==4) {write_com(0x80+6);write_data('4'); } else if(i1==5) {write_com(0x80+6);write_data('5'); } else if(i1==6) {write_com(0x80+6);write_data('6'); } else if(i1==7) {write_com(0x80+6);write_data('7');} else if(i1==8) {write_com(0x80+6);write_data('8');} else if(i1==9) {write_com(0x80+6);write_data('9');i1=-1;} if(i2==1&&i1==1) Awin(); } void chang2(void) { i2++; if(i2==1) {write_com(0x80+5);write_data('1');} if(i2==2) {write_com(0x80+5);write_data('2');} } void chang3(void) { i3++; if(i3==0) {write_com(0xC0+6);write_data('0');chang4();} else if(i3==1) {write_com(0xC0+6);write_data('1');} else if(i3==2) {write_com(0xC0+6);write_data('2');} else if(i3==3) {write_com(0xC0+6);write_data('3');} else if(i3==4) {write_com(0xC0+6);write_data('4');} else if(i3==5) {write_com(0xC0+6);write_data('5');} else if(i3==6) {write_com(0xC0+6);write_data('6');} else if(i3==7) {write_com(0xC0+6);write_data('7');} else if(i3==8) {write_com(0xC0+6);write_data('8');} else if(i3==9) {write_com(0xC0+6);write_data('9');i3=-1;} if(i3==1&&i4==1) Bwin();} void chang4(void) { i4++; if(i4==1) {write_com(0xC0+5);write_data('1');} if(i4==2) {write_com(0xC0+5);write_data('2');} } void delay(int q) { int x; for(;q>0;q--) for(x=19;x>0;x--) ; } //复位模块 void fuwei(void) { init(); write_com(0x80+2); write_data('A'); write_data(':'); write_data(' '); write_data('0'); write_com(0xC0+2); write_data('B'); write_data(':'); write_data(' '); write_data('0'); i1=0;i2=0;i3=0;i4=0; P1_6=0; chang0(); } void Awin(void) { write_com(0x80+7); write_data('W'); write_data('I'); write_data('N'); chang0(); } void Bwin(void) { write_com(0xC0+7); write_data('W'); write_data('I'); write_data('N'); chang0(); } 附录2:元件清单 电容 电阻
Proteus仿真: 元器件名称 型号/规格 数量 印制电路板 1 单片机 STCC51 1 石英晶体振荡器 12MHz 1 30PF 2 10μF 1 1KΩ 2 10 KΩ 1 电位器 50 KΩ 1 LCD显示屏 1602 1 三端稳压集成电路 7805 1 发光二极管 18 按键 11 译码器 74LS138 2
