嵌入式课程设计报告:51单片机贪食蛇游戏机设计

用51单片机做贪食蛇游戏机

本文配套的完整代码与工程下载地址:https://download.csdn.net/download/yul13579/53380773

目录

摘要

一、绪论

1.游戏机的发展与现状

2.项目可行性与意义

二、贪食蛇游戏机总体架构

2.1 游戏系统需求分析

2.1.1 游戏界面

2.1.2 游戏操控

2.1.3 游戏功能

2.1.4 游戏反馈

2.1.5 游戏运营

2.2 系统硬件总体架构

2.3 系统软件总体架构

三、贪食蛇游戏机硬件设计

3.1 显示部分

3.1.1 8x8点阵

3.1.2 LCD1602

3.2 输入部分

3.2.1 矩阵键盘

3.2.2 红外遥控

3.3 反馈部分

3.3.1 震动电机

3.3.2 蜂鸣器

3.4 存储部分

3.5 通信部分

3.5 传感器部分

四、贪食蛇游戏机软件设计

4.1 总体程序框图

4.2 8x8点阵LED程序设计

4.3 LCD1602程序设计

4.4 矩阵键盘程序设计

4.5 贪食蛇核心程序设计

4.6 上位机程序设计

五、系统测试与性能指标

5.1 系统运行效果

5.2 资源使用情况

5.3 系统性能指标

六、问题与解决方案

6.1 矩阵键盘与LCD1602冲突问题

6.2 程序存储器空间不足问题


摘要

从二十世纪五、六十年代起,游戏机从内容单一的投币机,到电视游戏机、街机、掌机,电子技术的发展也推动游戏机产业发生着巨大的变迁,每一代人对于儿时的游戏机都有着不同的记忆。

本项目将使用STC89C52单片机,在8x8点阵LED上实现贪食蛇游戏的运行,可以通过键盘、遥控器两种方式操作,具有调节难度、暂停、由光敏传感器实现的投币功能、由EEPROM实现的最高分记录功能,并辅以LCD1602、流水灯、蜂鸣器、电机实现丰富的声光电反馈效果。游戏算法上进行了新的设计,定义两个一维数组,利用位操作存储读取蛇头的运动状态信息。

51系列单片机技术成熟,功能强大,应用广泛。使用单片机作为控制核心,可以简化硬件电路,采用软件编程控制单片机实现硬件电路的功能,降低能耗,降低成本。软件采用C语言编程,方便灵活,大大加快了软件开发速度,缩短了开发周期,并且便于移植。

文中具体介绍了使用到的各种硬件的特性,游戏的各种功能与详细设计,软件的具体设计思路,各模块的详细介绍,部分模块的程序流程图,状态迁移图,关键部分代码的详细讲解等。

关键词:STC89C52;贪食蛇;游戏机

一、绪论

1.游戏机的发展与现状

        1972年,电视工程师Ralph Baer打造了世界上第一台家用游戏机 Odyssey(奥德赛),ATARI(雅达利)为Odyssey开发了一款叫《Pong》的网球游戏,这成为了世界上第一款电子游戏。《Pong》在现在看来是十分简陋的,只有简单的点和线条,但在当时的技术背景下,无疑是十分令人激动的创举。该时期的游戏机被称为第一世代。

40fab83dbf5244568c460103eb828442.png

 图1-1 游戏《Pong》界面

        凭借着《Pong》等游戏的巨大成功,雅达利迅速发展,1977上市的Atari 2600标志着游戏机进入第二世代。Atari 2600的配置为:1.19MHz MOS 6507八位处理器,机内128 bytes RAM和6Kb ROM。Atari 2600并不包含显示控制单元,而是直接利用了家用电视机的性能,最大支持160x192分辨率。第二世代游戏机还开创了游戏卡带的先河,每个游戏盘容量4KB,最高达10KB,用户如果想体验不同的游戏,只需要更换卡带,而不是再买一台游戏机。

        1983年,任天堂的Family Computer成为了第三世代游戏机的代表,国内称之为FC红白机。FC使用了一颗理光制造的1.8MHz 6502八位处理器,2KB RAM。处理器的数量也有所提升,FC还搭载了显存2KB的图像控制器(PPU)专门用于画面渲染,一个伪声音处理器(pAPU)用于驱动2个矩形波、1个三角波声道用于表现音乐,1个杂音通道用于表现爆炸等声效果,1个PCM合成音源用于表现连续的背景音。游戏卡带容量64KB,专用磁碟容量高达2MB。

        在之后的几十年里,游戏机不断更新换代,任天堂超级红白机SFC第一个搭载16位处理器,索尼PlayStation第一个使用CD-ROM ,游戏机性能在全面提升。如今年轻人所熟知的PS4、Xbox,也已经是第七世代游戏机,例如PS4搭载了2.9GHz主频的四核心APU,8GB RAM,专门用于高性能图像处理的1GHz GPU,搭配1GB专用显存,最大支持4096x2160分辨率。

        经过近50年的发展,游戏机不论是性能还是综合体验,确实已经不可同日而语。

2.项目可行性与意义

        此次项目使用的STC89C52单片机具有8KB ROM,512B RAM,3个16 位定时器/计数器,4个外部中断,主频最高35MHz,兼容MCS-51指令集。从数据上来看,STC89C52的纸面性能是远远超出第二世代游戏机的,甚至可以与FC红白机媲美,但实际上,由于我们缺少图像处理单元(PPU)来组成一个完整的游戏机系统,只用一片STC89C52并不能像FC红白机一样运行超级玛丽、魂斗罗之类具有复杂画面的游戏,但是通过驱动点阵LED来运行贪食蛇绰绰有余。

        本项目基于清翔QX-MCS51开发板,使用STC89C52和8x8点阵LED开发贪食蛇游戏,并利用开发板板载资源添加一系列功能,以提升个人单片机开发的实践应用能力。

二、贪食蛇游戏机总体架构

2.1 游戏系统需求分析

        贪吃蛇足一款经典小游戏,游戏的规则是:玩家通过方向键(上,下,左,右)来控制蛇移动,在地图上吃掉食物。吃掉食物后蛇身加长,并且会增加相应分数,达到一定分数以后提高难度级别,蛇身运动速度加快。蛇运动时撞到墙壁(屏幕边界)或者蛇身结束游戏。 

2.1.1 游戏界面

       贪食蛇游戏逻辑十分简洁,对画面的要求可高可低,使用点阵LED就能够完整地展现游戏内容:用LED灯代表每个像素点,每个食物占一个像素,多个点连起来构成蛇身,每吃到一个食物,蛇身会变长一个像素点。点阵LED的边界即为游戏地图的边界,出界或碰撞自己的身体都会导致游戏失败。

      除了游戏主界面外,我们还需要显示一些文字来引导用户如何开始游戏,在游戏中显示得分、难度等必要的信息,并向用户展示最高分记录,以增加游戏的挑战性。因此,需要增加一块液晶屏来实现这些功能。



2.1.2 游戏操控

        贪食蛇游戏的基本操控包括上、下、左、右四个基本方向操作,为了丰富游戏体验,本项目还引入了暂停/继续,增加、降低难度,一共7个操作项目。

        本项目提供了三种不同的操作方式,分别是:通过开发板上的矩阵键盘操作;通过红外无线遥控器操作;通过USB连接电脑上位机使用鼠标或键盘操作。尽可能多样化的操作方式,给用户提供了更多自由的选择。由于开发板上空间狭小,使用矩阵键盘非常容易疲劳,红外无线遥控和电脑键盘的使用体验会更加良好。



2.1.3 游戏功能

       本项目的贪食蛇游戏机提供暂停功能。用户可以在游戏进行中随时按下按键暂停游戏,进行放松休息,再按一次按键即可继续回到游戏。

除此之外,还提供难度设置功能。在游戏中,用户可以随时使用按键调整到适合自己的游戏难度。难度级别越高,蛇的移动速度越快,最低为1级,最高为9级。如果用户不主动调整,难度等级也会随着游戏的进行逐渐自动增加。



2.1.4 游戏反馈

        游戏的声光电反馈是丰富游戏体验的重要部分。除了最基本的屏幕显示外,本项目的贪食蛇游戏机会在蛇吃到食物得分时,发出清脆的提示音,同时顺次点亮一盏LED灯,在蛇出界或死亡时,则会发出低沉的提示音,同时启动电机带来振动效果。



2.1.5 游戏运营

        投币是游戏机带来收入的传统方式。玩家投入一个硬币后才能开始游戏,游戏角色死亡后,需要再次投入硬币才能继续游戏。

        其次,游戏机还应该具有最高分记录功能,让游戏具有目的性和挑战性,激励玩家不断努力打破记录。当然,还应该为游戏管理员提供方式来重置游戏的最高分记录。

2.2 系统硬件总体架构

        本系统硬件基于清翔MCS51开发板,并在此硬件基础上做了少量必要的调整。为了节约单片机I/O资源,大量外设采用共用总线的方式工作。具体硬件架构如图2-1所示。

a2b863c9c374420e88371c4023b06389.png

 图2-1 系统硬件架构图

2.3 系统软件总体架构

系统软件主要分为主函数和中断服务函数两部分。系统上电后,执行主函数进行必要的初始化操作,然后进入主循环,主循环采用了switch语句,对应欢迎界面、操作模式选择界面、游戏界面、暂停界面、结算界面,执行不同部分的程序。软件总体架构如图2-2所示。

a911dfd46dc14aa8bb5255c7c31c6875.png

 图2-2 系统软件架构图

三、贪食蛇游戏机硬件设计

3.1 显示部分

3.1.1 8x8点阵

8x8点阵LED如果使用直连的方式,共需要占用16个单片机I/O口,为了节约单片机宝贵的I/O资源,本项目使用了2片74HC595串入并出并带有锁存功能的位移缓存器,采用串行方式驱动点阵模块,只需占用3个单片机I/O口。74HC595与8x8点阵LED的原理图如图3-1所示。

6b40fb0e5d2840409f619088b31a5dff.jpg

 图3-1 8x8点阵LED串行驱动电路

3.1.2 LCD1602

LCD1602是内部集成字库的字符型液晶显示模块,内含32字节显示区RAM,一个字节对应屏幕上的一个字符,如图3-2所示。LCD1602内的CGROM已经存储了160种字符的编码,可以直接查表获得。在操作时,需要先确定显示的地址,即光标地址,再送入需要显示的字符编码。

adbff889977443a381b9cd6ac4fa41d6.png

 图3-2 LCD1602显示存储空间

      单片机与LCD1602的通信分为读状态、写指令、读数据、写数据四种操作模式,将EN、RW、RS引脚分别连接单片机的P3.4~P3.6,以控制操作模式。将RS置低、RW置高,为读状态模式,此时D0~D6脚输出当前地址指针值,D7脚输出忙信号。将RS、RW置低,为写指令模式,可以通过D0~D7脚写入指令。将RS、RW置高,为读数据模式,此时D0~D7脚输出当前指针所指向的RAM数据。将RS置高、RW置低,为写数据模式,通过D0~D7脚向当前指针所指向的RAM写入数据。RS、RW设置正确后,给使能引脚EN上升沿并保持,才能开始读、写操作,操作时序图如图3-3所示。

676fc19a65ab4047b5a93faf204144a3.png

 图3-3 LCD1602操作时序图

3.2 输入部分

3.2.1 矩阵键盘

        与独立按键不同,4x4矩阵键盘是通过行扫描和列扫描的方式,用8个I/O口实现16个按键的检测。硬件原理图如图3-4所示,行线为P30~P33,列线为P34~P37。

238a3fdab194482ea008c2b8a930f206.png

 图3-4 矩阵键盘原理图

        51单片机的P3口不是标准意义的双向口,是准双向口。双向口与准双向口的区别主要是:准双向口I/O口操作时做数据输入时需要对其置1。准双向口只能有效的读取0,而对1则是采用读取非零的方式,就是读入的时候要先向接口上写1,然后再读。

        具体原理为:向I/O口写1即为给锁存器写1,那么锁存器的反向端就输出0,和它相接的MOS管也就在截止状态,也就是呈高阻态,这样P0口上数据就会从读引脚的三态缓冲器上正确的输入。如果不向I/O口写1,那么锁存器上次锁存的可能为0,那么反向端有可能出现1,这样和反向端相接的MOS管导通,直接拉到地,那么不管你这个I/O口上输入什么信号都会被拉低,无法获得正确的输入结果。

3.2.2 红外遥控

        红外线遥控器已被广泛使用在各种类型的家电产品上,一般由红外发射装置和红外接收设备两大部分组成。红外发射装置又可由键盘电路、红外编码芯片、电源和红外发射电路组成。红外接收设备可由红外接收电路 红外解码芯片、电源和应用电路组成。通常为了使信号能更好的被传输发送端将基带二进制信号调制为脉冲串信号,通过红外发射管发射。常用的有通过脉冲宽度来实现信号调制的脉宽调制(PWM)和通过脉冲串之间的时间间隔来实现信号调制的脉时调制(PPM)两种方法。

        开发板所使用的TC9012红外遥控器,编码方式为PPM,发送的每一帧数据包含引导码、用户码、数据码,编码方式如图3-5所示。

e55c11fc84854ffaa1809a5c4ef4511d.png

ca8b1603d18b4d9082f17769d4187f26.png

  图3-5 TC9012的位编码方式

        TC9012晶振频率455KHz,经内部分频电路,将信号调制在37.91KHz通过红外发射,通过板载红外接收模块HS0038解调,由单片机软件解码。

3.3 反馈部分

3.3.1 震动电机

        ULN2003是大电流驱动阵列,具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。由七个硅NPN达林顿管组成。每一对达林顿都串联一个2.7K的基极电阻,在5V的工作电压下它能与TTL和CMOS电路 直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据。多用于单片机、智能仪表、PLC、数字量输出卡等控制电路中。可直接驱动继电器等负载。输入5VTTL电平,输出可达500mA/50V。

        本系统使用一片ULN2003来实现对130有刷直流电机的驱动,硬件连接如图3-6所示。

fef840b4a3b748b3a67fdd70f5fa7169.png

 图3-6 ULN2003驱动模块

3.3.2 蜂鸣器

        常见的蜂鸣器分为有源蜂鸣器和无源蜂鸣器,其根本区别是产品对输入信号的要求不一样。有源蜂鸣器工作的理想信号是直流电,因为蜂鸣器内部有一简单的振荡电路,能将恒定的直流电转化成一定频率的脉冲信号,从而实现磁场交变,带动铝片振动发音。无源蜂鸣器没有内部驱动电路,有些公司和工厂称为讯响器,国标中称为声响器。无源蜂鸣器工作的理想信号方波。如果给予直流信号蜂鸣器是不响应的,因为磁路恒定,钼片不能振动发音。

        为了使电路尽量简单、成本低廉,这里使用了一个有源蜂鸣器,硬件原理图如图3-7所示。

38caa07190ce42afb3945cee20d16271.png

 3-7 有源蜂鸣器

3.4 存储部分

STC89C52运行中产生的数据存储在片内RAM中,这些数据在芯片掉电后会一并丢失。如果有些需要灵活读写且长期保存的数据,就需要将这些数据存储在EEPROM中。

24C02是一个2K位串行CMOS EEPROM, 内部含有256个8位字节,一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,对于STC89C52单片机,则需要通过软件IIC实现操作。硬件原理图如图3-8所示。

00a701a253a1470a886d0c70cb7437e0.png

 图3-8 EEPROM芯片24C02

3.5 通信部分

89C52与上位机采用串口通信。CH340 是一个 USB 总线的转接芯片,可以实现 USB 转串口、USB 转 IrDA红外或者 USB 转打印口。CH340 芯片支持 5V 电源电压或者 3.3V 电源电压。当使用 5V 工作电压时,CH340 芯片的 VCC 引脚输入外部 5V 电源,并且 V3引脚应该外接容量为 4700PF 或者 0.01μF 的电源退耦电容。当使用 3.3V 工作电压时,CH340 芯片的 V3 引脚应该与 VCC 引脚相连接。同时输入外部的 3.3V电源,并且与 CH340 芯片相连接的其他电路的工作电压不能超过 3.3V。

在计算机端的 Windows 操作系统下,CH340 的驱动程序能够仿真标准串口,可以进行串口操作,与绝大部分原串口应用程序完全兼容,通常不需要作任何修改。CH340 可以用于升级原串口外围设备,或者通过 USB 总线为计算机增加额外串口。通过外加电平转换器件,可以进一步提供 RS232、RS485、RS422等接口。其硬件电路连接如图 3-9 所示。

3a58da77f35c4755bf06a6a8c18587af.png

 图3-9 CH340串口通信模块

3.5 传感器部分

模数转换芯片XPT2046是一种典型的逐次逼近型模数转换器(SARADC),包含了采样/保持、模数转换、串口数据输出等功能。同时芯片集成有一个2.5V的内部参考电压源、温度检测电路,工作时使用外部时钟。XPT2046可以单电源供电,电源电压范围为2.7V~5.5V。参考电压值直接决定ADC的输入范围,参考电压可以使用内部参考电压,也可以从外部直接输入1V~VCC范围内的参考电压(要求外部参考电压源输出阻抗低)。X、Y、Z、VBAT、Temp和AUX模拟信号经过片内的控制寄存器选择后进入ADC,ADC可以配置为单端或差分模式。硬件接线如图3-10所示。

f9a25f784e0f401895766993c956d451.png

 图3-10 XPT2046硬件接线图
 

四、贪食蛇游戏机软件设计

4.1 总体程序框图

系统上电后,将执行main函数进行必要的初始化操作。程序的主循环主体采用了switch语句,根据运行状态标志位game_state值,对应到欢迎界面、操作模式选择界面、游戏界面、暂停界面、结算界面,执行不同部分的程序。main函数程序框图如图4-1所示。

5db1f4cf7328406ca3a18d77962d96a7.jpg

  图4-1 系统主函数程序框图

      系统的中断资源使用了定时器0中断、定时器1中断、外部中断0。定时器0中断。定时器0中断每50ms触发一次,根据当前难度等级,当计时位累计达到一定值时将更新一次蛇的坐标,并判断是否得分或死亡。外部中断0用于捕捉红外遥控信号的下降沿,并打开定时器1计算红外遥控信号的低电平持续时间,如果检测到有效的引导码,则开始记录接下来的低电平时长数据存储在irdata[]中。中断服务函数程序框图如图4-2所示。

7ab3f2a8c9e449dbac3985a968e37019.jpg

  图4-2 中断服务函数程序框图

4.2 8x8点阵LED程序设计

        74HC595是串入并出并带有锁存功能的位移缓存器,通过SER脚串行输入数据,SCK每一次上升沿,使得74HC595将SER脚的输入送入内部寄存器,其他高位依次上移一位,移满8位后,第一片74HC595将会通过最高位Q7脚将数据送入第二片74HC595的最低位,从而组成16位串入并出位移缓存器。全部的16位数据写入完成后,RCK引脚触发一次上升沿,可以将74HC595的数据锁存在输出端。这样,我们送入16位串行数据,就可以在8x8点阵上点亮对应的LED。

      查数据手册,74HC595芯片的脉冲宽度应该在20ns以上。通过单片机I/O对74HC595进行操作时,考虑到STC89C51在11.0592MHz下,执行一个nop指令耗时约为1us,因此我们可以直接使用nop指令来进行通信时序的调整。

      上述功能的C语言代码实现如图4-3所示。函数LED88_send_byte(u8 dat)功能是将一组八位数据dat按上述的位移时序规则送入74HC595,函数LED88_point(u8 x, u8 y)内部调用了两次LED88_send_byte(u8 dat),功能是将一个点的坐标转化为与8x8点阵对应8位行数据、8位列数据,依次送入74HC595,并锁存在输出端。

6adf615300e447a8aedd4b5455a3eeed.png

fa70d3222e414e3eb5f52b09632c7c49.png

 图4-3 8x8点阵模块显示函数

      用两个一维数组snake_x[],snake_y[]记录蛇身坐标,(snake_x[0], snake_y[0])为蛇头坐标。在更新蛇移动后的坐标时,只需要将snake_x[]和snake_y[]中的数据后移一位,并根据前进方向重新计算蛇头坐标即可。具体C语言函数如图4-4所示。

0f7c587d404247eaa2a9b64717b7ce32.png

 图4-4 贪食蛇移动计算函数

4.3 LCD1602程序设计

        在本项目中,需要用到的LCD1602操作主要有读忙信号、写指令、写数据。

        LCD1064内部执行操作需要耗费一定时间,通常是毫秒级。先将D0~D7置高,作为输入引脚,将RS置1,RW置0,读D7脚电平,如果没有忙信号,可以直接进行下一步操作,如果LCD忙,需要循环查询D7脚直到忙信号结束,才能执行下一项操作。将读忙信号的操作封装成C语言函数LCD1602_Read_Busy(),函数的具体内容如图4-5所示。

afe6007155a3429c9ecb9449cccdc9e4.png

 图4-5 读忙信号函数

      写指令和写数据都是通过D0~D7口并行写入八位数据,区别在于写指令是对LCD1602功能、模式、指针地址的设置,写数据则是直接向指针指向的RAM地址上写入数据。在执行写操作前,都需要按上述方法查询忙信号。首先置位RS、RW选择操作模式:RS、RW置低为写指令模式;RS置高、RW置低为写数据模式。然后将要写入的八位指令或数据并行送入D0~D7,将EN脚拉高产生上升沿,送入八位指令或数据。写指令和写数据的C语言函数内容如图4-6所示。

41569447f72f4f33b9e4643d25cd5f4b.png

  图4-6 写指令和写数据函数

      在显示字符时,首先要使用写指令函数LCD1602_Write_Cmd(u8 cmd)写入RAM指针的地址。需要注意的是,LCD1602在写入光标地址时要求D7脚为高电平,例如将光标插入第二行第一位,需写入的数据是01000000B(40H)|10000000B(80H)=11000000B(C0H)。确定指针地址后,才可以使用写数据函数LCD1602_Write_Dat(u8 dat)写入字符对应的编码。

        为了提高程序的可读性,我们用两个坐标参数x,y来直观地表示LCD上的16x2显示区域,函数LCD1602_Dis_OneChar(u8 x, u8 y, u8 dat)可以实现在指定位置显示一个字符的功能。如果在初始化时打开了光标自动移动,指针会自动指向下一个地址,利用这个特性,可以便捷地打印一段字符串,而不需要每手动更新指针地址,将该功能封装到函数LCD1602_Dis_Str(u8 x, u8 y, u8 *str)中,传入参数x,y为起始位置,*str为字符串首地址。具体C语言代码如图4-7所示。

dc982fa464b54299919f2b614b410258.png

  图4-7 显示字符和显示字符串

4.4 矩阵键盘程序设计

        根据P3口的特性,当我们采用扫描的方式读矩阵键盘时,先向行线写低电平,作为输出引脚,列线写高电平,作为输入引脚,此时读列线数据,若列线出现低电平,说明该列有按键按下。再向行线写高电平,向列线写低电平,读行线数据,确定是该列哪一行的按键按下,从而确定键值。具体函数如图4-8所示。

a528ae23822840fa94248defaff50b77.png

图4-8 矩阵键盘扫描函数

        为避免按键机械结构接触时的不稳定导致按键被多次触发,需要在检测到有按键按下后,进行一个短暂的延时进行消抖处理。为了避免按键长时间按下造成反复触发,在检测到按键的最后一步,应当进行松手检测,若按键仍为按下状态,则在while语句中等待,直至按键松开。

4.5 贪食蛇核心程序设计

        用两个一维数组snake_x[],snake_y[]记录蛇身坐标,(snake_x[0], snake_y[0])为蛇头坐标。在更新蛇移动后的坐标时,只需要将snake_x[]和snake_y[]中的数据后移一位,并根据前进方向重新计算蛇头坐标即可。C语言函数如图4-9所示。

a5fbc1affa3a425597978bbaaacdd498.png

  图4-9 贪食蛇移动坐标更新

      当蛇吃到食物点时,长度将会增长一个点位。首先更新数组,将刚刚消失的一个点前移一位,重新归入数组的有效长度范围内,然后length变量加一,同时使用位操作按顺序点亮一盏LED灯,驱动蜂鸣器发出短暂的提示音。完成数组的操作和声光提示后,更新下一个食物位置坐标,使用头文件stdlib.h提供的随机变量生成函数rand()生成一个范围在0~32767之间的随机数,除以8求余数得到一个范围在0~7之间的随机数,对应8x8点阵LED的范围。用这样的方法生成X、Y两个随机坐标之后,还需要遍历当前snake数组的0~length-1位,判断随机生成的这个食物坐标是否与蛇身重叠,如果重叠,再次调用函数自身,重新创建食物。上述功能的C语言实现如图4-10所示。

b88ddcd67d6f445ba04c12cd64253516.png

  图4-10 得分判断与随机食物点创建

       根据贪食蛇游戏规则,蛇在碰撞到游戏边界或自己的身体时,将会死亡,游戏结束。

        当蛇碰撞下边界、左边界时,当前蛇头坐标应该为8,当蛇碰撞下边界、左边界时,当前蛇头坐标应该为-1,由于存储蛇坐标的数组为八位无符号数,不存在-1,故此时数组中的值应当为255,因此只要判断蛇头X、Y坐标的值是否大于等于7,就可以判断出蛇是否碰撞到边界死亡。判断蛇是否碰撞到自身死亡时,需要遍历数组进行判断。如果判断到蛇死亡,游戏结束,启动蜂鸣器和震动电机,通过for循环保持一段时间,并通过在每次for循环末尾添加1ms延时,产生更加低沉的声音,与得分时的提示音加以区分。上述功能的C语言代码如图4-11所示。

a3dbaabd82404b74a5436af4274de5e9.png

图4-11 贪食蛇死亡判断

4.6 上位机程序设计

      上位机是由C++QT编写的UI界面,主要包括键盘事件重载和串口通信。

      在上位机软件界面上,有串口控制区和游戏控制区。选择正确的端口号,点击“打开串口”,在clicked事件的槽函数中将会调用openSerialPort函数初始化该串口,波特率默认9600,数据位8,停止位1,无校验位。串口初始化函数如图4-12所示。

5e9cebe3550a4cf5b79f67dabf218ab3.png

 图4-12 上位机串口初始化函数

      对于游戏控制区按钮,则是在按钮clicked事件的槽函数中,调用串口函数发送一个值,不同的值对应了不同的指令,例如0x02代表“上”,0x10代表“暂停/继续”,由单片机串口收到串口数据后加以执行。

        为了使操作更加便利,上位机支持直接使用键盘操作。重载QT提供的键盘事件,映射到相应的按键槽函数发送相应指令。键盘事件重载函数如图4-13所示。

d37f4d5461e14ac3b08c8b3ed8217314.png

 图4-13 上位机键盘事件槽函数

五、系统测试与性能指标

5.1 系统运行效果

        系统上电之后,进入欢迎界面,液晶屏显示“Welcome!”,第二行“INSERT COIN”字样闪烁,如图5-1所示,提醒玩家投币开始游戏。

e4cd1568565d4a19857f8fe8d008a526.png

         图5-1 欢迎界面

      投入一枚硬币以后,进入操作模式选择界面,通过独立按键选择操作模式。左数第一个按键为矩阵键盘模式,第二个按键为红外遥控模式,第三个按键为上位机模式。如图5-2所示。

65b86d34c9c643d98682b5c657f6dfca.png

 图5-2 模式选择界面

      选择操作模式之后,系统倒数三秒钟进入游戏,蛇将出生在点阵LED左下角,初始长度为3,玩家可以通过所选择的操作模式开始游戏。图5-3展示的是使用红外遥控操作游戏。

d0cbed01de9d499f8cb04dd204ce3bb9.png

 图5-3 游戏进行中

      游戏提供暂停和难度等级调节功能,玩家可以在游戏过程中随时按独立按键S2或红外遥控绿色播放键暂停游戏,进入图5-4所示界面;按独立按键S3或红外遥控减号键降低游戏难度等级,按独立按键S4或红外遥控加号键提高游戏难度等级。使用上位机操作时,点击按钮或按键盘上对应的按键也可以实现相同操作。

65d89bb1a8d24d079727a9efe16c4897.png

 图5-3 游戏暂停

      当贪食蛇碰撞到边界或自身死亡后,游戏结束,进入结算界面。如果本次游戏没有打破最高分记录,游戏结算界面则会有“GAME OVER”字样闪烁,并显示本次得分。如果本次游戏打破最高分纪录,游戏过程中在LCD右侧将会显示“new record”字样,如图5-3所示,结算界面将会有“CONGRADULATIONS!”字样闪烁,对玩家表示祝贺,并显示新纪录的分数,如图5-4所示,同时将该记录更新到EEPROM中。该数据存储在 EEPROM中,开发板掉电后数据不会丢失,可以一直保存,因此,该游戏机的所有玩家都可以在任何时间挑战该游戏机内的最高分记录。

f8e40fccc8ed482b9661589c69ba1c59.png

 图5-4 游戏结算界面(刷新纪录)

      为了便于游戏运营者管理,可以通过特殊手段清除记录。在游戏结算界面时,按下独立按键S5,最高分记录将会被清零,LCD短暂地显示“Reset complete”,如图5-5所示,然后立即退出到欢迎界面。

80636e2d20984391aad49780f1d30010.png

 图5-5 重置最高分记录

       游戏上位机软件由C++QT编写,分为串口控制和游戏控制两个部分你,界面如图5-6所示。当前游戏控制区按钮处于禁用状态,在正确连接串口后,将会使能游戏控制区按钮。按下键盘上对应的按键,也可以实现相同的效果。

f826f829c4344186a0e4c5d7d4443e88.png

 图5-6 上位机软件界面

5.2 资源使用情况

        使用的STC89C52单片机内部资源包括:四组I/O的输入输出、2个定时器中断、1个外部中断、内部拓展RAM。

        程序存储器(ROM)占用率52.82%,数据存储器(RAM)占用率62.03%,外部扩展程序存储器(External RAM)占用率5.33%。

        使用的开发板外设资源包括:液晶屏LCD1602、8x8点阵LED、矩阵键盘、独立键盘、流水灯、蜂鸣器、电机驱动、EEPROM、红外遥控、光敏传感器。

5.3 系统性能指标

        由于没有足够的仪器设备,这里仅通过示波器大致测得以下性能数据:系统主循环执行频率约90.9Hz(因执行内容不同,数值会有所不同),理论最大按键操作延迟11ms,理论最大红外遥控操作延迟14ms,理论最大上位机操作延迟11ms,测试上位机通信丢包率0%,误码率0%(有线通信)。

六、问题与解决方案

6.1 矩阵键盘与LCD1602冲突问题

        LCD1602的数据总线接单片机P0口,控制引脚接单片机P3.4-P3.6口,而矩阵键盘接入单片机P3口,两者将会发生冲突。在进行矩阵键盘扫描时,EN脚将会被拉高,此时P0口的状态并不确定,从而会在EN产生高电平时将一组未知的数据送入LCD1602,造成液晶显示乱码。

        为了解决这个问题,我从两个方面入手。一方面,由于本系统并不需要用到所有的按键,因此在安排键位时,避免使用与液晶屏EN脚共用IO的一行和一列,避免其反复跳变造成的不确定性。另一方面,在扫描LCD之前将单片机P0口置位0xff,以避免送入不确定的数据,同时将矩阵键盘扫描程序置于LCD刷新程序之前,这样即便导致了显示错误,也能在一次主循环中及时刷新掉。

        经测试,系统基本上解决了LCD与矩阵键盘的总线冲突问题,在扫描和按下矩阵键盘时不会出现LCD乱码。

6.2 程序存储器空间不足问题

        在本系统中,贪食蛇长度最长为64个点,每个点由2个字节表示,仅仅这些就要花掉128字节RAM。在STC89C51中,片内RAM大小为256字节,其中高128字节为特殊功能寄存器,仅有低128字节中的一少部分可供用户自由定义变量使用,因此本系统所需要的RAM空间远远超出51单片机的片内资源,在编译时会出现RAM寻址超出限制的错误。

        不过STC89C52属于增强型的51单片机,查数据手册可知,STC89C52提供了1024字节的内部扩展RAM,这一部分RAM空间物理上属于内部,集成在单片机片内,而逻辑上是外部,使用MCS51的MOVX指令访问,在C语言中,在声明变量时使用关键字xdata即可将该变量定义在1024字节的内部扩展RAM中,解决RAM不足的问题。

硬件环境:清翔51开发板

开发环境:Keil 5

配套完整工程下载地址:https://download.csdn.net/download/yul13579/53380773

  • 15
    点赞
  • 142
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河上七月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值