基于单片机的俄罗斯方块游戏机课程设计.docx

上传人:b****5 文档编号:27759745 上传时间:2023-07-04 格式:DOCX 页数:18 大小:799.35KB
下载 相关 举报
基于单片机的俄罗斯方块游戏机课程设计.docx_第1页
第1页 / 共18页
基于单片机的俄罗斯方块游戏机课程设计.docx_第2页
第2页 / 共18页
基于单片机的俄罗斯方块游戏机课程设计.docx_第3页
第3页 / 共18页
基于单片机的俄罗斯方块游戏机课程设计.docx_第4页
第4页 / 共18页
基于单片机的俄罗斯方块游戏机课程设计.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

基于单片机的俄罗斯方块游戏机课程设计.docx

《基于单片机的俄罗斯方块游戏机课程设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的俄罗斯方块游戏机课程设计.docx(18页珍藏版)》请在冰豆网上搜索。

基于单片机的俄罗斯方块游戏机课程设计.docx

基于单片机的俄罗斯方块游戏机课程设计

《单片机原理及应用》

课程设计报告

 

题目:

俄罗斯方块游戏机

专业:

电子信息工程技术

班级:

电子B1512班

学号:

姓名:

指导老师:

 

2017-12-01

 

1.设计题目、要求及分工

1.1设计题目

本课程设计题目是基于51单片机的俄罗斯方块游戏机。

1.2设计要求

本课程设计主要器件是STC89C52单片机和液晶12864,通过单片机发生信号控制液晶屏的显示,使用按键实现游戏的开始、暂停、移动、翻转等。

1.3分工

在本次设计中,张荣俊同学主要负责软件的设计与分析,汤青红同学负责硬件电路的设计。

2.设计方案

本次设计采用STC89C52单片机控制模块,USB电源模块来提供电源,复位模块,12864LCD显示屏进行屏显,晶振与电容实现时钟电路,按键直接接入I/O口,这样可以简化电路。

另外我们还采用了6个按键,分别是左移,右移,下移、方块变化键、确定按键与暂停按键。

3.系统硬件电路设计

3.1硬件设计整体方框图

 

图3.1硬件设计框图

3.2电源系统

本设计的电源系统比较简单,由USB电源输出5V电源进行供电,具体电路如下图所示:

图3.2电源电路

3.3STC89C52单片机介绍

图3.3STC89C52引脚图

P1口

P1是一个带内部上拉电阻的8位双向I/O口,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。

对端口写"1",通过内部的上拉电阻把端口拉到高电平,此时可作输入口。

作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。

与AT89C51不同之处是,P1.0和P1.1还可分别作为定时/计数器2的外部计数输入(P1.0/T2)和(P1.1/T2EX)。

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输出固定的脉冲信号,因此它可对外输出时钟或用于定时目的。

要注意的是:

每当访问外部数据存储器时将跳过一个ALE脉冲。

对Flash存储器编程期间,该引脚还用于输入编程脉冲(PROG)。

如有必要,可通过对特殊功能寄存器(SFR)区中的8EH单元的D0位置位,可禁止ALE操作。

该位置位后,只有一条MOVX和MOVC指令才能将ALE激活。

此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE禁止位无效。

PSEN

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

在此期间,当访问外部数据存储器,将跳过两次PSEN信号。

EA/VPP

外部访问允许。

欲使CPU仅访问外部程序存储器(地址为0000H-FFFFH),EA端必须保持低电平(接地)。

需注意的是:

如果加密位LB1被编程,复位时内部会锁存EA端状态。

如EA端为高电平(接Vcc端),CPU则执行内部程序存储器中的指令。

Flash存储器编程时,该引脚加上+12V的编程允许电源Vpp,当然这必须是该器件是使用12V编程电压Vpp。

XTAL1

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

XTAL2

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

3.4复位电路设计

单片机在启动时都需要复位,以使CPU及系统各部件处于确定的初始状态,并从初态开始工作。

89系列单片机的复位信号是从RST引脚输入到芯片内的施密特触发器中的。

当系统处于正常工作状态时,且振荡器稳定后,如果RST引脚上有一个高电平并维持2个机器周期(24个振荡周期)以上,则CPU就可以响应并将系统复位。

单片机系统的复位方式有:

手动按钮复位和上电复位。

 手动按钮复位需要人为在复位输入端RST上加入高电平(图1)。

一般采用的办法是在RST端和正电源Vcc之间接一个按钮。

当人为按下按钮时,则Vcc的+5V电平就会直接加到RST端。

手动按钮复位的电路如所示。

由于人的动作再快也会使按钮保持接通达数十毫秒,所以,完全能够满足复位的时间要求。

复位电路连接如图所示:

图3.4复位电路

3.5时钟电路设计

8XX51系列单片机的时钟信号通常用两种电路形式得到:

内部振荡方式和外部振荡方式。

在引脚XTAL1和XTAL2外接晶振,就构成了内部振荡方式。

由于单片机内部有一个高增益反相放大器,当外接晶振后,就构成了自激振荡器,并产生振荡时钟脉冲。

晶振通常选用6MHz、12MHz或24MHz。

本次设计中我们选用了12MHz的晶振,晶振与锁相环电路配合使用,以提供系统所需的时钟频率。

设计中STC89C52使用12MHz晶体振荡器作为振荡源,由于单片机内部带有振荡电路,所以外部只要连接一个晶振和两个电容即可,电容容量一般在15pF到50pF之间,我们选用电容容量为33pF的电容,如图所示即为本设计的振荡电路。

图3.5时钟电路

 

3.6液晶屏显示模块

液晶显示屏是整个系统硬件的重要组成部分,担当着人机交互的重要角色。

本设计采用铭正同公司生产的MzL02D-12864液晶点阵屏作为显示器件。

它是一块128*64点阵的LCD显示模组,模组上的LCM采用COG技术将控制(包括显存)、驱动器集成在LCM的玻璃上,接口简单,操作方便。

其特点为单电源供电,对比度编程可调,可采用并行接口为6800/8080时序或者串行SPI的MPU接口方式,整块液晶屏由3.3V的白色LED背光,美观大方。

其外接部分分为电源端口、数据端口和命令端口三部分组成。

本设计中LCD的数据端口连接到STC89C51单片机的P0端口,LCD命令端口连接到单片机的P2端口。

具体实物如图所示:

图3.6液晶屏正面图图3.7液晶屏反面图

图3.8液晶屏显示电路

3.7按键电路设计

按键电路模块是智能俄罗斯方块游戏系统的输入器件,它的控制器包括六个按键,分别为:

左移、变形、右移、暂停、下降、确定。

具体硬件电路如下图所示。

图3.8按键电路

4.软件系统的设计

4.1软件系统设计框图

 

Y

图4.1软件系统设计框图

5.调试结果记录及分析

5.1仿真结果

图5.1仿真电路图

5.2实物调试结果

图5.2实物主界面图图5.3实物速度设置界面图

图5.4实物游戏界面图图5.5实物游戏得分界面图

5.6实物游戏结束界面图

6.心得体会

我在这次中主要负责软件的调试以及协调好软硬键的通讯。

软件调试中,发现了乱码的现象,开始调试是弄不清是软件的问题还是硬件的问题,这给了我一个很大的教训,软件硬件不能同时调试,只有确认一个没问题后才能更好的调试另一个。

最后发现是由软件引起数据冲突造成的。

此外还出现的各种各样的BUG,例如游戏得分系统和人机通讯系统也会出现问题,有个问题更是莫名其妙,比如按着按着出现界面停顿现象,甚至出现了死机现象,而实际游戏中这种现象是万万不允许的。

开始以为是电平干扰所引起的,但是接稳定的电压也会出现这种情况。

回去检查代码时已经是1000多行代码了,从主函数慢慢往下看,虽然注释的比较详细但是问题却很难找到,然而BUG事实却摆在那里。

不修复则游戏无法进行。

我终于体会到程序员的辛苦和无奈。

只能回到最初的流程图从底层驱动函数和算法逻辑慢慢整理,才发现我的程序出现的多么大的问题,没有用好指针,指针出现了问题给程序带来的灾难性的后果。

还有一些变量的初始化没有赋值,

初始化指针中没用明确的指向,函数没有返回。

这些都是细节问题,任何一个关键变量没有用好都会出现很大的问题。

更重要的教训是编程思路一定要清晰,这就要求编写代码之前流程图都要画好。

还有就是编写程序时头脑要清醒不能打疲劳战,有时候变量的赋值过程中脑袋里想的是赋值为1而键盘中赋值的确实0;这种情况也是最难找的,因为是自己写的程序,潜意识以为是正确的,就去找别处的错误了。

只有一个一个的找才能找出来。

找到之后,真的很后悔当初的粗心

 

参考文献

[1]张毅刚.单片机原理及接口技术[M].北京:

人民邮电出版社,2013:

220-240

[2]郭天祥.新概念51单片机C语言教程[M].北京:

电子工业出版社,2012:

230-240

[3]韩旭,王娣.C语言从入门到精通[M].北京:

清华大学出版社,2010:

244-260

[4]胡仁喜.AltiumDesigner16从入门到精通[M].北京:

机械工业出版社,2016:

118-168

[5]王东锋,董冠强.单片机C语言应用100例[M].北京:

电子工业出版社,2009:

182-200

附录1

整体电路原理图:

PCB图:

附录2

元件清单:

元件名称

规格

元件名称

规格

可调电阻

10K

单片机

STC89C52

按键

6个

液晶显示屏

LCD12864

晶振

12M

滑动变阻器

10K

瓷片电容

33PF

USB母座

1个

附录3

关键函数如下所示:

①俄罗斯方块中文显示界面

voidgame_start_show()

{

bittpflag=1;//置循环标志位为1

LCD_full_draw(start_pic);

while(tpflag)

{

switch(basic_button())

{

case6:

tpflag=0;

speaker=0;

while(button_b==0);

speaker=1;

break;

default:

;

}

}//game_start_showÑ»·

}

②选择游戏难度级别

voidselect_speed()

{

unsignedchari;

bittpflag=1;//置循环标志为1

LCD_clear();

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

{

LCD_display_byte(i,0,0xff);

LCD_display_byte(i,7,0xff);

}

LCD_display_byte(60,4,0x7f);

LCD_display_byte(59,4,0x3e);

LCD_display_byte(58,4,0x1c);

LCD_display_byte(57,4,0x08);

LCD_display_byte(67,4,0x7f);

LCD_display_byte(68,4,0x3e);

LCD_display_byte(69,4,0x1c);

LCD_display_byte(70,4,0x08);

LCD_display_word(speed_data,24,3,52);

show_speed_num(62,4);

while(tpflag)

{

switch(basic_button())

{

case4:

if(speed_num!

=0)

{

speaker=0;

speed_num--;

show_speed_num(62,4);

speaker=1;

}

while(left==0);

break;

case5:

if(speed_num!

=9)

{

speaker=0;

speed_num++;

show_speed_num(62,4);

speaker=1;

}

while(right==0);

break;

case6:

tpflag=0;

speaker=0;

while(button_b==0);

speaker=1;

break;

default:

;

}

}//选择游戏速度循环

}

③人机通信(进行游戏)

voidTetris_main()

{

unsignedchari;

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

{

Box_Ram[i]=Box_Ram_data[i];

};//载入游戏初始化显示画面

LCD_draw(mpic);

game_over_flag=0;//游戏结束标志位置0表示游戏未结束

box_build();

box_load();

box_to_Box_Ram(s_box.x,s_box.y,s_box.box);

box_down_reg=(20-(speed_num<<1)-1);//为了使方块一出现就能变换形状,所以需要尽快使得方块下降一行,不知道为什么最高行不行变换形状

time0_initialize();

while(!

game_over_flag)//如果游戏结束标志位置1,表示游戏结束,打破循环,调用游戏结束画面显示函数

{

game_button();

}

EA=0;//游戏结束后关总中断

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 育儿理论经验

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1