版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、<p> 本科畢業(yè)論文(設(shè)計)</p><p> 題 目: 基于單片機的推箱子游戲設(shè)計 </p><p> 學(xué)生姓名: 徐衛(wèi) 學(xué)號: P30914093 </p><p> 院(系): 電子信息工程 專業(yè): 微電子 </p><
2、p> 入學(xué)時間: 2009 年 9 月</p><p> 導(dǎo)師姓名: 楊宗立 職稱/學(xué)位: 講師 </p><p> 導(dǎo)師所在單位: 安徽大學(xué) </p><p> 完成時間: 2013 年 5 月</p><p>
3、; 基于PROTEUS的推箱子游戲的設(shè)計</p><p><b> 摘 要</b></p><p> 本論文主要介紹了基于單片機的推箱子游戲的規(guī)則、硬件結(jié)構(gòu)、軟件代碼的編寫及工作原理、基于T6963C內(nèi)核的液晶模塊PG160128A的詳細(xì)介紹以及指令集。模擬出Windows系統(tǒng)下的推箱子游戲,具有任意關(guān)數(shù)選擇、難度依次加大、游戲步數(shù)記錄、游戲時間記錄、按鍵發(fā)聲、
4、系統(tǒng)低功耗、可實現(xiàn)在線調(diào)試等特點。本系統(tǒng)是以單片機為其控制核心,以有源晶振構(gòu)成的電路作為時鐘信號,通過方向鍵的選擇向單片機控制系統(tǒng)發(fā)出人物移動控制命令,控制系統(tǒng)接收命令后做出一系列必要的判斷后,控制人物及箱子的移動。本設(shè)計已通過了實驗仿真,運行穩(wěn)定,基本上沒有規(guī)則方面的錯誤。</p><p> 論文主要分為兩大塊:一塊為游戲的硬件電路組成部分,一塊為軟件程序設(shè)計部分。在硬件電路里主要包括有源晶振部分、方向控制部
5、分及液晶顯示部分等與單片機的接線設(shè)計;軟件編程方面主要是子程序和主程序的編寫,包括:初始化代碼、液晶驅(qū)動代碼、方向按鍵代碼、過關(guān)判斷代碼、步數(shù)記錄代碼、時間記錄代碼、按鍵發(fā)聲代碼、關(guān)數(shù)選擇代碼及表格數(shù)據(jù)代碼等等。所有這些在文中都有詳細(xì)說明。</p><p> 關(guān)鍵詞:單片機;推箱子;PG160128A; T6963C內(nèi)核;指令集</p><p> Design Of PROTEUS S
6、okoban Game Based On[1]</p><p><b> Abstract</b></p><p> This paper introduces the single-chip based on the rules of the game Sokoban, the structure of hardware, software code writi
7、ng and working principle, based on the core T6963C LCD module PG160128A, as well as details of the instruction set. Simulate the system under Windows Sokoban game, an arbitrary number of related options, in turn increase
8、 the difficulty of the game a few step-by-step record time of the game record, sound button, low-power system can achieve on-line debugging and so on. The s</p><p> Key words:MCU; Sokoban; PG160128A; T6963C
9、 core; instruction set</p><p><b> 目錄</b></p><p> 1 推箱子游戲編譯介紹7</p><p> 2 推箱子游戲的硬件部分設(shè)計7</p><p> 2.1 PG160128A液晶屏介紹7</p><p> 2.2 T6963C及其指
10、令集介紹9</p><p> 2.2.1 T6963C9</p><p> 2.3 晶振、復(fù)位電路10</p><p> 2.3.1 晶振電路10</p><p> 2.3.2 復(fù)位電路11</p><p> 2.4 液晶顯示屏與單片機接口電路11</p><p> 3
11、推箱子游戲的軟件部分設(shè)計13</p><p> 3.1 液晶屏驅(qū)動代碼設(shè)計15</p><p> 3.1.1 讀狀態(tài)程序15</p><p> 3.1.2 是否可讀寫程序15</p><p> 3.1.3 是否可自動讀寫程序16</p><p> 3.1.4寫單參數(shù)程序16</p>
12、<p> 3.1.5寫雙參數(shù)程序16</p><p> 3.1.6寫指令程序17</p><p> 3.1.7寫8字節(jié)數(shù)據(jù)程序17</p><p> 3.1.8設(shè)置數(shù)據(jù)顯示在屏幕上的坐標(biāo)程序17</p><p> 3.1.9設(shè)置數(shù)據(jù)存儲起始地址17</p><p> 3.1.10 CGR
13、AM偏置地址設(shè)置函數(shù)18</p><p> 3.1.11液晶初始化函數(shù)18</p><p> 3.1.12顯示一個漢字子程序18</p><p> 3.1.13 清屏程序18</p><p> 3.1.14 自定義字符寫入CGROM函數(shù)19</p><p> 3.1.15 設(shè)置點顯示在屏幕上的坐標(biāo)(
14、以位為單位)19</p><p> 3.1.16 畫圓子程序,其中x0,y0表示圓心,R表示半徑19</p><p> 3.2 初始化代碼設(shè)計20</p><p> 3.3 游戲時間代碼設(shè)計20</p><p> 3.4 游戲選關(guān)代碼設(shè)計20</p><p> 3.5 步數(shù)、關(guān)數(shù)更新代碼設(shè)計21&
15、lt;/p><p> 3.5.1 步數(shù)更新代碼設(shè)計21</p><p> 3.5.2 關(guān)數(shù)更新代碼設(shè)計21</p><p> 3.6 過關(guān)代碼設(shè)計21</p><p> 3.7圖形顯示子程序22</p><p> 3.7.1 地圖顯示子程序22</p><p> 3.7.2原來
16、位置顯示子程序22</p><p> 3.8 中斷代碼設(shè)計23</p><p> 3.8.1 定時器0中斷發(fā)聲程序23</p><p> 3.8.2 定時器1中斷計時程序23</p><p> 3.9 方向控制代碼設(shè)計23</p><p> 4 推箱子游戲的系統(tǒng)仿真25</p>&
17、lt;p> 4.1建立工程項目流程25</p><p> 4.2 Proteus中原理圖的繪制及文件的加載29</p><p> 4.3 開機界面顯示31</p><p> 4.4 游戲界面顯示31</p><p> 4.5 仿真結(jié)果分析及解決方法33</p><p><b> 5
18、 總結(jié)34</b></p><p><b> 參考文獻(xiàn).34</b></p><p><b> 致謝35</b></p><p> 1 推箱子游戲編譯介紹</p><p> 現(xiàn)如今,游戲風(fēng)靡全球,各種游戲?qū)映霾桓F,大到網(wǎng)絡(luò)型的復(fù)雜游戲,小到手機游戲、單機游戲、智力游戲等簡單
19、游戲。但是這種簡單也是相對于網(wǎng)絡(luò)游戲等大型游戲而言的,小游戲本身的代碼還是相當(dāng)繁雜,它要執(zhí)行一系列指令才能正確的完成一個簡單的操作,才能按照玩家的意志工作。所以我們現(xiàn)在見到的游戲多是在基于電腦這種高速執(zhí)行指令的平臺上運行的,脫離了它就什么事都做不了了。那么推箱子這種小游戲能否在單片機上編出來呢?答案是肯定的。首先,這個游戲是一個小型游戲,實現(xiàn)的功能比較簡單,不像大型游戲那樣功能復(fù)雜,它只要控制人物將所有箱子推到正確的位置即可,難度隨著箱
20、子的增多而加大,對于實現(xiàn)這樣一個功能,程序不是太復(fù)雜,用一塊單片機足以達(dá)到目的。其次,它的控件也比較少只有4個方向鍵和2個輔助的功能鍵,這些控鍵在Proteus中用彈跳式按鍵代替即可。第三,游戲地圖相對比較小、畫面簡單,只有箱子、人物和正確位置箱子等幾個圖形,這些在一塊稍大的液晶屏上就足以顯示,用不著電腦顯示屏。第四,就編程語言方面來說,編寫這樣一個簡單的小游戲不需要什么高級的語言,C語言或匯編語言就足以完成,C語言是一種通用型的語言,
21、編程靈活、可讀性強、</p><p> 2 推箱子游戲的硬件部分設(shè)計</p><p> 本部分內(nèi)容包括介紹PG160128A及其引腳功能;介紹T6963C指令集;晶振電路、復(fù)位電路的硬件設(shè)計;控件及按鍵發(fā)聲電路設(shè)計,最后給出游戲仿真的整體硬件電路圖,接下來是具體的說明。</p><p> 2.1 PG160128A液晶屏介紹[2]</p><
22、;p> PG160128A為一個128行160列的點陣液晶屏,他能顯示各種字符、圖形、漢字,基于T6963C內(nèi)核控制,自帶字符庫,同時用戶也可以自己建立漢字、圖形庫,其在Proteus中的元器件圖形如下: </p><p> 圖1 PG160128 </p><p> 各引腳的功能描敘如下表: </p><p&
23、gt; 表一 PG160128引腳功能表</p><p> 2.2 T6963C及其指令集介紹</p><p> 2.2.1 T6963C[3]</p><p> T6963C是一個LCD控制器,可設(shè)計為用于液晶顯示器控制驅(qū)動芯片和數(shù)據(jù)顯示的存取器。該控制器有一個8位并行數(shù)據(jù)總線,控制線的讀取或?qū)懭胪ㄟ^微控制器接口實現(xiàn),可以直接連接到TMPZ80微處理器中。
24、它有一個128字節(jié)的字符發(fā)生器也可以控制外部顯示RAM中的數(shù)據(jù),達(dá)64K字節(jié)。配置的文字,圖形和外部字符發(fā)生器RAM數(shù)據(jù)能很容易控制其顯示在窗口中,可以自由移動、分配內(nèi)存范圍。該器件支持非常廣泛的字符格式,液晶顯示器允許通過編程設(shè)置選擇不同的組合。它可以用于文字,圖形和結(jié)合文本模式及其他各種屬性的功能。</p><p> 2.2.2 T6963C指令集[4]</p><p> T696
25、3C共分為十大類,26條指令,詳細(xì)信息如下表:</p><p> 表二 T6963C指令集</p><p> 2.3 晶振、復(fù)位電路</p><p> 2.3.1 晶振電路</p><p> 單片機的晶振電路如圖2所示,其中XTAL1和XTAL2分別為片內(nèi)振蕩電路的輸入輸出端。一般電容取20~47uF,本系統(tǒng)晶體的振蕩頻率為24MHz
26、。晶振電路產(chǎn)生的振蕩脈沖經(jīng)過內(nèi)部觸發(fā)器進(jìn)行二分頻后,成為單片機的時鐘脈沖信號,為單片機提供一個基本時鐘信號。</p><p><b> 圖2 晶振電路</b></p><p> 2.3.2 復(fù)位電路</p><p> 復(fù)位操作是單片機的基本操作,單片機在進(jìn)入運行前和在運行過程中程序出錯或操作失誤使系統(tǒng)不能正常運行時,需要進(jìn)行復(fù)位操作,復(fù)位
27、操作后,程序?qū)?000H開始重新執(zhí)行。</p><p> 復(fù)位信號從單片機的RST引腳輸入,復(fù)位操作有上電自動復(fù)位、按鍵電平復(fù)位和外部脈沖復(fù)位三種方式,本電路采用了按鍵電平復(fù)位,電路圖如圖3.。</p><p><b> 圖3 復(fù)位電路</b></p><p> 2.4 液晶顯示屏與單片機接口電路</p><p>
28、; 液晶顯示屏共有18個引腳,其中VDD、RST兩腳接電源,VSS、FS1、CE三腳接地,CON、FG兩腳懸空,D0~D7分別與單片機P2.0~P2.7相連接,WR與P1.7腳相連,RD與P1.6腳相連,C/D與P1.5腳相連,電路圖見圖4.</p><p> 2.5 控鍵、喇叭與單片機接口電路</p><p> 本游戲共有6個控件,分別是:四個方向鍵,用于控制箱子的移動方向;一個確
29、定鍵,用于刷新初始化界面進(jìn)入游戲界面;一個選關(guān)鍵,用于選關(guān)。一個喇叭,用于按鍵發(fā)聲,以提示按鍵是否有效,電路圖見圖4.</p><p> 控件、喇叭與單片機的接線是:上移鍵接P1.0;左移鍵接P1.1;右移鍵接P1.2;下移鍵接P1.3;確定鍵接P1.4;選關(guān)鍵接P1.5;喇叭經(jīng)過分壓式偏置共射放大電路將信號放大再與單片機P3.1口相連,如圖4:</p><p> 圖4 揚聲器放大電路
30、</p><p> 至此,游戲的硬件電路結(jié)構(gòu)及連線全部介紹完成,仿真電路圖如圖5所示,整個電路圖以網(wǎng)絡(luò)標(biāo)號的形式給出,避免連線過多顯得電路擁擠。</p><p> 圖5 推箱子游戲硬件電路圖</p><p> 3 推箱子游戲的軟件部分設(shè)計</p><p> 本部分主要介紹游戲的軟件部分設(shè)計,包括液晶屏驅(qū)動代碼設(shè)計;初始化代碼設(shè)計游戲時
31、間代碼設(shè)計;游戲關(guān)數(shù)代碼設(shè)計;游戲步數(shù)代碼設(shè)計;過關(guān)代碼設(shè)計;方向控制代碼設(shè)計;按鍵發(fā)聲代碼設(shè)計;數(shù)據(jù)表格設(shè)計等幾個方面,現(xiàn)就對這幾個方面做具體分析。</p><p> 3.1 液晶屏驅(qū)動代碼設(shè)計[5]</p><p> 3.1.1 讀狀態(tài)程序</p><p> unsigned char Read_State()//返回液晶顯示屏的當(dāng)前狀態(tài)</p>
32、;<p> {unsigned char a;</p><p> P2=0xff;//讀狀態(tài)之前先將數(shù)據(jù)線拉高</p><p> _CD=1;// 為指令、狀態(tài)操作條件</p><p> _RD=0;//讀操作條件</p><p> _RD=1;//為下次讀做準(zhǔn)備</p><p> a=Pin
33、;//將狀態(tài)保存</p><p> return a;}</p><p> 3.1.2 是否可讀寫程序</p><p> void Enable()</p><p> {while(1) //bit0指令寫狀態(tài)位,bit1數(shù)據(jù)讀/寫狀態(tài)位,為1時候空閑</p><p> if((Read_State()&am
34、p;3)==3)break;}//如果狀態(tài)的低2為1則可讀寫</p><p> 3.1.3 是否可自動讀寫程序</p><p> void Aut_Write()</p><p> {while(1) //bit3數(shù)據(jù)自動寫狀態(tài)位,為1時候空閑</p><p> if((Read_State()&8)==8)break;} /
35、/如果狀態(tài)的第4為1則可自動讀寫</p><p> 3.1.4寫單參數(shù)程序</p><p> //Data1為傳入的參數(shù),Com為傳入的指令;寫入順序為先數(shù)據(jù)后寫指令。</p><p> void Write_Data1(unsigned char Data1,unsigned char Com)</p><p> {Enable()
36、;//判斷是否可讀寫</p><p> _CD=0;//為數(shù)據(jù)操作條件</p><p> Pin=Data1;//將數(shù)據(jù)送數(shù)據(jù)線</p><p> _WR=0;//寫操作</p><p> _WR=1;//為下次寫做裝備</p><p><b> Enable();</b></p&
37、gt;<p> _CD=1; // 為指令、狀態(tài)操作條件</p><p> Pin=Com; //將指令送數(shù)據(jù)線</p><p><b> _WR=0;</b></p><p><b> _WR=1;}</b></p><p> 3.1.5寫雙參數(shù)程序</p>
38、<p> // Data1/Data2為傳入的參數(shù),Com為傳入的指令,先Data1后Data2,最后寫指令。</p><p> void Write_Data2(unsigned char Data1,unsigned char Data2,unsigned char Com)</p><p> {Enable();//判斷是否可讀寫</p><p&g
39、t; _CD=0; //為數(shù)據(jù)操作條件</p><p> Pin=Data1; //將數(shù)據(jù)1送數(shù)據(jù)線</p><p> _WR=0; //寫操作</p><p> _WR=1; //為下次寫做裝備</p><p><b> Enable();</b></p><p><b>
40、 _CD=0;</b></p><p> Pin=Data2; //將數(shù)據(jù)2送數(shù)據(jù)線</p><p><b> _WR=0;</b></p><p><b> _WR=1;</b></p><p><b> Enable();</b></p>
41、<p><b> _CD=1;</b></p><p> Pin=Com; //將指令送數(shù)據(jù)線</p><p><b> _WR=0;</b></p><p><b> _WR=1;}</b></p><p> 3.1.6寫指令程序</p>&
42、lt;p> void Write_Com(unsigned char Com)</p><p> {Enable();//判斷是否可讀寫</p><p> _CD=1; // 為指令、狀態(tài)操作條件</p><p> Pin=Com; //將指令送數(shù)據(jù)線</p><p> _WR=0;//寫操作</p><p
43、> _WR=1;}//為下次寫做裝備</p><p> 3.1.7寫8字節(jié)數(shù)據(jù)程序</p><p> // Addr表示數(shù)據(jù)首地址,Way表示寫的方式</p><p> void Write_8_Data(unsigned char Addr,unsigned char Way)</p><p> {Aut_Write();/
44、/判斷是否能自動寫</p><p> Write_Com(AUT_WR);//自動寫開始</p><p> Write_Data1(Addr,Way);</p><p> Write_Com(AUT_WO);}//自動寫結(jié)束</p><p> 3.1.8設(shè)置數(shù)據(jù)顯示在屏幕上的坐標(biāo)程序</p><p> //
45、(以字節(jié)為單位),x表示顯示的行(0~15),y表示顯示的列(0~19)</p><p> void Set_xy(unsigned char x,unsigned char y)</p><p> {unsigned int a;a=x*20+y;</p><p> Write_Data2(a&0xff,a>>8,ADR_POS);}&l
46、t;/p><p> 3.1.9設(shè)置數(shù)據(jù)存儲起始地址</p><p> void Set_Addr(unsigned char Addr1,unsigned char Addr2)</p><p> {Write_Data2(Addr1,Addr2,ADR_POS);}</p><p> 3.1.10 CGRAM偏置地址設(shè)置函數(shù)</p
47、><p> void Set_CGRAM()</p><p> {Write_Data2(1,0,CGR_POS);}</p><p> 3.1.11液晶初始化函數(shù)</p><p> //(文本區(qū)首地址D1,文本區(qū)首地址D2, 文本區(qū)寬度, 圖形區(qū)首地址D1, </p><p> //圖形區(qū)首地址D2, 圖形區(qū)
48、寬度, 光標(biāo)形狀, 顯示方式, 顯示開關(guān))</p><p> void LCD_Init(unsigned char Txt1,unsigned char Txt2,unsigned char Txt_Wide,</p><p> unsigned char Map1,unsigned char Map2,unsigned char Map_Wide,</p>&
49、lt;p> unsigned char Guang_Biao,unsigned char Disp_Mode,unsigned char Kai_Guan)</p><p> {Write_Data2(Txt1,Txt2,TXT_STP);</p><p> Write_Data2(Txt_Wide,0,TXT_WID);</p><p> Write
50、_Data2(Map1,Map2,GRH_STP);</p><p> Write_Data2(Map_Wide,0,GRH_WID);</p><p> Write_Com(CUR_SHP|Guang_Biao);</p><p> Write_Com(Disp_Mode);</p><p> Write_Com(DIS_SW|Ka
51、i_Guan);}</p><p> 3.1.12顯示一個漢字子程序</p><p> //x表示顯示的行(0~15),y表示顯示的列(0~19),n表示字在表格中的位置</p><p> void Han_Zi(unsigned char x,unsigned char y,unsigned char Addr)</p><p>
52、{Set_xy(x,y);</p><p> Write_8_Data(Addr,INC_WR);</p><p> Write_8_Data(Addr+2,INC_WR);</p><p> Set_xy(x+1,y);</p><p> Write_8_Data(Addr+1,INC_WR);</p><p&g
53、t; Write_8_Data(Addr+3,INC_WR);}</p><p> 3.1.13 清屏程序</p><p> void Clear_LCD()</p><p> {unsigned int a;</p><p> Set_xy(0,0);//從最左上角開始</p><p> for(a=0;
54、a<320;a++)//清屏320字節(jié)</p><p> Write_8_Data(0x83,INC_WR);}// 數(shù)據(jù)寫,地址加1</p><p> 3.1.14 自定義字符寫入CGROM函數(shù)</p><p> void Write_CGORM()</p><p> {unsigned int a;</p>&
55、lt;p> Set_CGRAM();Set_Addr(0,0x0c);</p><p> for(a=0;a<992;a++)//992字節(jié)</p><p> Write_8_Data(Tab[a],INC_WR);}</p><p> 3.1.15 設(shè)置點顯示在屏幕上的坐標(biāo)(以位為單位)</p><p> //x表示顯
56、示的行(0~127),y表示顯示的列(0~159),n=1表示打一點,n=0清除一點</p><p> void Point(unsigned char x,unsigned char y,bit n)</p><p> {unsigned char point;</p><p> unsigned int temp;</p><p>
57、 temp=x*20+y/8+320;point=0xf7-y%8;</p><p> if(n)point|=0xf8;</p><p> else point&=0xf7;</p><p> Write_Data2(temp&0xff,temp>>8,0x24);//設(shè)置寫地址</p><p> W
58、rite_Com(point);}</p><p> 3.1.16 畫圓子程序,其中x0,y0表示圓心,R表示半徑</p><p> //先打第一象限內(nèi)的1/4段圓弧,再依據(jù)對稱原理打出其他3段圓弧</p><p> void Circle(unsigned char x0,unsigned char y0,unsigned R,bit n)</p>
59、;<p> {unsigned char i,j=0;</p><p> Point(x0,y0,n);</p><p> for(i=0;i<=R;i++)</p><p> { while(1)</p><p> { if(R*R-i*i<=j*j)break; j++;}</p><
60、;p> Point(x0-j,y0+i,n);Point(x0-i,y0+j,n); //第一象限打點</p><p> Point(x0+j,y0+i,n);Point(x0+i,y0+j,n); //第二象限打點</p><p> Point(x0+j,y0-i,n);Point(x0+i,y0-j,n); //第三象限打點</p><p> Po
61、int(x0-j,y0-i,n);Point(x0-i,y0-j,n); //第四象限打點</p><p><b> j=0; }}</b></p><p> 3.2 初始化代碼設(shè)計[6]</p><p> //初始化代碼里包含定時器0、1的相關(guān)參數(shù)設(shè)置,初始化開機界面顯示等。</p><p> EA=ET0=E
62、T1=1;//開啟中斷總開關(guān),允許外部中斷0、1中斷</p><p> TMOD=0x11;//將定時器0、1都設(shè)為定時模式且工作在方式一。</p><p> TH0=64800/256;//定時器0初始值裝載,用于按鍵發(fā)聲</p><p> TL0=64800%256;</p><p> TH1=0x3c;// 定時器1初始值裝載,
63、每25ms中斷一次</p><p><b> TL1=0xb0;</b></p><p> Init_disply();//調(diào)用開機界面顯示子函數(shù),包含了開機界面的所有內(nèi)容</p><p> 3.3 游戲時間代碼設(shè)計</p><p> if(F) //當(dāng)程序檢測到讀時間標(biāo)志位F=1(由定時器1控制)時會刷新一次時
64、間。</p><p> {F=0;//為下一次做準(zhǔn)備</p><p> Set_xy(13,17);//設(shè)置百位數(shù)字顯示的位置</p><p> Write_8_Data(0x10+Time/100,0xc4);//得到時間的百位數(shù)據(jù)</p><p> Set_xy(13,18); //設(shè)置十位數(shù)字顯示的位置</p>&
65、lt;p> Write_8_Data(0x10+Time%100/10,0xc4);//得到時間的十為數(shù)據(jù)</p><p> Set_xy(13,19); //設(shè)置個位數(shù)字顯示的位置</p><p> Write_8_Data(0x10+Time%10,0xc4);}//得到時間的個位數(shù)據(jù)</p><p> 3.4 游戲選關(guān)代碼設(shè)計</p>
66、<p> //當(dāng)按下選關(guān)按鍵后,主程序調(diào)用選關(guān)函數(shù),程序代碼如下:</p><p> void Choice_Customs()</p><p> {Time=Steps=0;//選關(guān)時將時間、步數(shù)歸零</p><p> New_Step();//更新步數(shù)顯示</p><p> Custom=Cust;//將選得的關(guān)傳
67、給關(guān)數(shù)寄存器</p><p> New_Custom();//更新關(guān)數(shù)顯示</p><p> Dispaly();//更新地圖顯示</p><p> Cust++;//沒按下一次鍵鍵關(guān)數(shù)加一</p><p> if(Cust==18)Cust=1;}//如果關(guān)數(shù)等于18則回到第一關(guān)(游戲總共17關(guān))</p><p&
68、gt; 3.5 步數(shù)、關(guān)數(shù)更新代碼設(shè)計[7]</p><p> 3.5.1 步數(shù)更新代碼設(shè)計</p><p> //當(dāng)按下任意一個方向鍵,且箱子能移動時,會調(diào)用游戲步數(shù)更新子程序</p><p> void New_Step()</p><p> {Set_xy(7,17); //設(shè)置百位數(shù)字顯示的位置</p><
69、;p> Write_8_Data(0x10+Steps/100,0xc4); //得到步數(shù)的百位數(shù)據(jù)</p><p> Set_xy(7,18); //設(shè)置十位數(shù)字顯示的位置</p><p> Write_8_Data(0x10+Steps%100/10,0xc4); //得到步數(shù)的十位數(shù)據(jù)</p><p> Set_xy(7,19); //設(shè)置個位數(shù)
70、字顯示的位置</p><p> Write_8_Data(0x10+Steps%10,0xc4);} //得到步數(shù)的個位數(shù)據(jù)</p><p> 3.5.2 關(guān)數(shù)更新代碼設(shè)計</p><p> void New_Custom()</p><p> {Set_xy(1,18);// 設(shè)置十位數(shù)字顯示的位置</p><p
71、> Write_8_Data(0x10+Custom/10,0xc4);// 得到關(guān)數(shù)的十位數(shù)據(jù)</p><p> Set_xy(1,19);// 設(shè)置個位數(shù)字顯示的位置</p><p> Write_8_Data(0x10+Custom%10,0xc4);}// 得到關(guān)數(shù)的個位數(shù)據(jù)</p><p> 3.6 過關(guān)代碼設(shè)計</p><
72、;p> //當(dāng)所有箱子都推到指定位置時,會調(diào)用過關(guān)子程序,代碼如下:</p><p> void Pass()</p><p> {unsigned char i,j,a=1;//內(nèi)存空間分配</p><p> for(i=0;i<8;i++)//掃描8行</p><p> {if(!a)break;//如果a=0則直接
73、跳出函數(shù)</p><p> for(j=0;j<9;j++) //掃描9列 </p><p> //如果關(guān)卡數(shù)組表格中此位置是叉圖形或箱子和叉重合后的圖
74、 </p><p> if(Customs[Custom-1][i][j]==5||Customs[Custom-1][i][j]==4)</p><p> //如果動作跟蹤數(shù)組里此位置是箱子和叉重合后的圖,則將a置1</p><p> if(Follow_Action[i][j]==5)a=1;
75、</p><p> //如果動作跟蹤數(shù)組里此位置不是箱子和叉重合后的圖,則將a置0,并退出</p><p> else {a=0;break;}}</p><p> if(a){Custom++;//如果a=1則將關(guān)數(shù)加一(因為所有箱子都已推好,可以過關(guān))</p><p> Steps=Time=0;//過關(guān)時將時間、步數(shù)歸零<
76、/p><p> New_Step();//更新步數(shù)顯示</p><p> if(Custom==18)Custom=1;//如果關(guān)數(shù)等于18則回到第一關(guān)(游戲總共17關(guān))</p><p> New_Custom();//更新關(guān)數(shù)顯示</p><p> Dispaly();}}//更新地圖顯示</p><p> 3
77、.7圖形顯示子程序</p><p> 圖形顯示子程序包括地圖顯示程序和原來位置顯示子程序兩個</p><p> 3.7.1 地圖顯示子程序</p><p> //在調(diào)用過關(guān)函數(shù)或選關(guān)函數(shù)時,會調(diào)用到顯示子函數(shù),功能是刷新地圖</p><p> void Dispaly()</p><p> {unsigned
78、 char i,j,a;</p><p> for(i=0;i<8;i++)//掃描8行</p><p> {for(j=0;j<9;j++)//掃描9列</p><p> {Follow_Action[i][j]=Customs[Custom-1][i][j];將關(guān)卡數(shù)組中的數(shù)據(jù)傳給跟蹤數(shù)組
79、 </p><p> a=Follow_Action[i][j];//將跟蹤數(shù)組中的數(shù)據(jù)傳給動態(tài)內(nèi)存</p><p> switch(a)//
80、根據(jù)內(nèi)存中的數(shù)據(jù)做出判斷</p><p> {case 0:a=0x80;break;//如果是0(空白)則將空白字模的地址80H傳給內(nèi)存</p><p> //如果是1(人物)則將人物字模的地址94H傳給內(nèi)存,并記錄人物位置所在坐標(biāo)</p><p> case 1:a=0x94;x_Coordinate=i;y_Coordinate=j;break;<
81、/p><p> case 2:a=0x84;break;// 如果是2(墻壁)則將墻壁字模的地址84H傳給內(nèi)存</p><p> case 3:a=0x8c;break;// 如果是3(箱子)則將箱子字模的地址8cH傳給內(nèi)存</p><p> case 4:a=0x88;break;// 如果是4(叉)則將叉字模的地址88H傳給內(nèi)存</p><
82、p> case 5:a=0x90;break;}//如果是5(箱子和叉重合)則將地址90H傳給內(nèi)存</p><p> Han_Zi(2*i,2*j,a);}}}//調(diào)用寫漢字程序,將圖形顯示出來</p><p> 3.7.2原來位置顯示子程序</p><p> //此程序顯示當(dāng)人物移動后,人物本身位置所要顯示的圖形</p><p&g
83、t; void _Display()</p><p> {if(a==0||a==3||a==1) //如果原來人物這個位置是空白或是箱子則顯示一個空白</p><p> {Han_Zi(2*x_Coordinate,2*y_Coordinate,0x80);// 將空白圖形顯示出來</p><p> Follow_Action[x_Coordinate][
84、y_Coordinate]=0;}//更新跟蹤數(shù)組中的內(nèi)容</p><p> //如果人物本身這里是一個叉圖形或是箱子或叉重合后的圖則顯示一個叉</p><p> if(a==4||a==5)</p><p> {Han_Zi(2*x_Coordinate,2*y_Coordinate,0x88);// 將叉圖形顯示出來</p><p>
85、; Follow_Action[x_Coordinate][y_Coordinate]=4;}}// 更新跟蹤數(shù)組中的內(nèi)容</p><p> 3.8 中斷代碼設(shè)計</p><p> 中斷代碼設(shè)計包括定時器0和1兩段,定時器0為中斷發(fā)聲代碼,定時器1為中斷計時代碼,代碼如下:</p><p> 3.8.1 定時器0中斷發(fā)聲程序</p><p
86、> void Time_0_Int() interrupt 1 using 0</p><p> {TH0=64800/256;TL0=64800%256;//定時器0初值設(shè)定</p><p> Count++;//每次進(jìn)入中斷,發(fā)聲計數(shù)數(shù)據(jù)加1</p><p> if(Count==150)TR0=Count=0;//發(fā)聲100ms后Count中數(shù)據(jù)
87、歸零,并關(guān)定時器</p><p> Speaker=~Speaker;}//喇叭引腳電平取反</p><p> 3.8.2 定時器1中斷計時程序</p><p> void Time_1_Int() interrupt 3 using 1</p><p> {TH1=0x3c;TL1=0xb0;// 定時器1初值設(shè)定</p>
88、;<p> Counts++;//每次進(jìn)入中斷,計時計數(shù)數(shù)據(jù)加1</p><p> if(Counts==40)//如果1秒中到</p><p> {Counts=0;Time++;F=1;}}// Counts數(shù)據(jù)歸零,時間全局量加1,讀時間標(biāo)志置1</p><p> 3.9 方向控制代碼設(shè)計[8]</p><p>
89、 游戲共有4個方向鍵,每一個鍵代碼編寫的原理,判斷順序及執(zhí)行何種操作都是一樣的,不同的是方向各不相同,現(xiàn)已向上推箱子為例詳細(xì)說明其執(zhí)行過程。</p><p> void On_Push()//向上推子函數(shù)</p><p> {Cust=1;//關(guān)數(shù)計數(shù)器置一,為選關(guān)做準(zhǔn)備</p><p> a=Customs[Custom-1][x_Coordinate][y
90、_Coordinate];//原來人物這個位置是什么</p><p> b=Follow_Action[x_Coordinate-1][y_Coordinate]; //現(xiàn)在人物位置上面是什么
91、 </p><p> if(b==0||b==4)//如果現(xiàn)在人物位置上面是空白或是叉圖形則顯示一個人物</p><p> {Steps++;//箱子可以移動,步數(shù)加1</p><p> New_Step();//更新步數(shù)</p><
92、;p> Han_Zi(2*(x_Coordinate-1),2*y_Coordinate,0x94);//在上面顯示人物</p><p> _Display();//調(diào)用原來位置顯示子程序,還原人物本身位置圖形</p><p> x_Coordinate--;}//更新人物坐標(biāo)</p><p> if(b==3||b==5)//如果現(xiàn)在人物位置上面是箱
93、子或是箱子和叉重合的圖形則還得判//斷人物上面的上面是什么圖形,如果人物上面的上面不是箱子、墻壁和箱子和叉//重合后的圖形則可以移動</p><p> {if(Follow_Action[x_Coordinate-2][y_Coordinate]!=2&&Follow_Action[x_Coor</p><p> dinate-2][y_Coordinate]!=3&a
94、mp;&Follow_Action[x_Coordinate-2][y_Coordinate]!=5)</p><p> {Steps++;//箱子可以移動,步數(shù)加1</p><p> New_Step();//更新步數(shù)</p><p> //如果現(xiàn)在人物位置上面的上面是空白</p><p> if(Follow_Action
95、[x_Coordinate-2][y_Coordinate]==0)</p><p> {Han_Zi(2*(x_Coordinate-2),2*y_Coordinate,0x8c);//則在上面的上面顯示個箱子</p><p> Follow_Action[x_Coordinate-2][y_Coordinate]=3;}//更新箱子的位置</p><p>
96、 //如果現(xiàn)在人物位置上面的上面是叉</p><p> else if(Follow_Action[x_Coordinate-2][y_Coordinate]==4)</p><p> {//則在上面的上面顯示一個箱子和叉重合后的圖</p><p> Han_Zi(2*(x_Coordinate-2),2*y_Coordinate,0x90);</p&g
97、t;<p> Follow_Action[x_Coordinate-2][y_Coordinate]=5; }//更新箱子和叉重合的位置</p><p> Han_Zi(2*(x_Coordinate-1),2*y_Coordinate,0x94); //在上面顯示一個人物</p><p> //如果現(xiàn)在人物位置上面是箱子則更新為空白(因為箱子已經(jīng)移掉了)</p&
98、gt;<p> if(b==3)Follow_Action[x_Coordinate-1][y_Coordinate]=0;</p><p> //如果現(xiàn)在人物位置上面是箱子和叉重合的圖則更新為叉(因為箱子已經(jīng)移掉了)</p><p> if(b==5)Follow_Action[x_Coordinate-1][y_Coordinate]=4;</p>&
99、lt;p> _Display();//調(diào)用原來位置顯示子程序,顯示人物本身位置所要顯示的圖形</p><p> x_Coordinate--;//更新人物坐標(biāo)</p><p> Pass();}}}//調(diào)用過關(guān)子程序,判斷是否過關(guān)</p><p> 4 推箱子游戲的系統(tǒng)仿真[9,10,11,12]</p><p> 在仿真前
100、先介紹有關(guān)工程項目的建立及編譯生成可執(zhí)行文件(*.Hex)的具體過程。</p><p> 4.1建立工程項目流程</p><p> 1)建立一個新工程 單擊Project菜單,在彈出的下拉菜單中選中New Project選項,如下圖 </p><p> 2)然后選擇你要保存的路徑,輸入工程文件的名字,比如保存到C51目錄里,工程文件的名字為C51,如下圖所示
101、,然后點擊保存.</p><p> 3)這時會彈出一個對話框,要求你選擇單片機的型號,你可以根據(jù)你使用的單片機來選擇,keil c51幾乎支持所有的51核的單片機,我這里還是以大家用的比較多的Atmel 的89C51來說明,如下圖所示,選擇89C51之后,右邊欄是對這個單片機的基本的說明,然后點擊確定.</p><p> 4)完成上一步驟后,屏幕如下圖所示 </p>&l
102、t;p> 5)在下圖中,單擊“File”菜單,再在下拉菜單中單擊“New”選項 ,如果已經(jīng)寫好了C文件則直接添加為文件,這一步可去掉。</p><p> 新建文件后屏幕如下圖所示</p><p> 在建立目標(biāo)文件之前,首先要將文件添加到組里去。具體操作如下:將鼠標(biāo)箭頭移至中間左邊項目窗口中的“Source Group 1”前的圖標(biāo)上,再單擊鼠標(biāo)右鍵,在彈出的菜單項中選擇“Add
103、 files to Group ‘Source Group 1’”。在彈出的對話框中選擇剛才編輯保存好的源程序文件;需點“文件類型”右側(cè)文本框中的倒三角,在彈出的下拉菜單中選“All files(*.*)”,然后再找到程序文件。點“Add”按鈕,再在彈出的對話框中選擇文件類型,如“Assembly language file”;再點“Close”按鈕。若是C語言源程序文件“*.c”;或匯編語言的源程序文件“*.asm”,則點“文件類型
104、”右側(cè)文本框中的倒三角,在彈出的下拉菜單中選“c source file”或“asm source file”,然后再找到程序文件。點“Add”按鈕,再點“Close”按鈕。此時按鈕建立目標(biāo)“Build target”前的編譯當(dāng)前文件“Translate current file”按鈕的顏色也變深了。而在中間左邊項目窗口中的“Source Group 1”前多了一個“+”號。</p><p> Keil中文件的
105、添加</p><p> 完成上述操作后方可進(jìn)入建立目標(biāo)文件。通常先點編譯當(dāng)前文件“Translate current file”,再建立目標(biāo)文件“Build target”;或直接點重建目標(biāo)文件“Rebuild all target files”。即可生成我們需要的后綴名為HEX的十六進(jìn)制文件。編譯或匯編的結(jié)果見如圖所示,上面提示“0個錯誤、0個報警”。如果在編譯、連接中出現(xiàn)錯誤,則可按照提示進(jìn)行檢查。這個文件
106、就是我們要下載到單片機中的程序文件。</p><p> 圖6 Keil工程項目目標(biāo)文件生成</p><p> 4.2 Proteus中原理圖的繪制及文件的加載</p><p> 依照仿真電路在Proteus中繪圖,如下圖所示</p><p> Proteus中的推箱子原理圖</p><p> 雙擊單片機彈出
107、對話框,在Clock Frequency欄中將晶振設(shè)置為24MHz,在Program file欄中加載“推箱子.Hex”文件,再單擊OK設(shè)置完成,圖片如下:</p><p> 單片機文件加載及晶振設(shè)置</p><p> 至此仿真前的準(zhǔn)備工作都已經(jīng)全部完成,接下來正式進(jìn)入仿真調(diào)試。</p><p> 4.3 開機界面顯示</p><p>
108、 點擊仿真按鈕,程序調(diào)用初始化函數(shù),進(jìn)入開機界面顯示,圖片如下:</p><p> 4.4 游戲界面顯示</p><p> 當(dāng)進(jìn)入開機界面顯示后,只有確定鍵有效,其他按鍵被鎖定,當(dāng)按下確定鍵后,確定鍵失效,其他鍵鎖定解除,畫面進(jìn)入第一關(guān)游戲界面顯示,關(guān)數(shù)、步數(shù)、時間開始記錄數(shù)據(jù),圖片如下:</p><p> 第一關(guān)游戲界面 第四關(guān)
109、游戲界面</p><p> 第六關(guān)游戲界面 第八關(guān)游戲界面</p><p> 第十關(guān)游戲界面 第十二關(guān)游戲界面</p><p> 第十四關(guān)游戲界面 第十七關(guān)游戲界面</p><p> 4.5 仿真結(jié)果分析及解決方法</p><p>
110、通過以上給出的仿真波形分析可知,本設(shè)計中的各項功能夠很好的實現(xiàn)。在時鐘脈沖的作用下,各個按鍵都能按照事先設(shè)定好的規(guī)則進(jìn)行游戲控制。確定鍵能使界面從初始化顯示切換到游戲界面顯示,上下左右鍵控制箱子的移動方向,如果可以移動則移動方塊同時跟蹤人物的位置及刷新動態(tài)數(shù)組的內(nèi)容。在游戲的同時程序會隨時記錄玩家所走的游戲步數(shù)、游戲時間,直至本關(guān)通過,在進(jìn)入下一關(guān)的同時更新地圖并刷新游戲步數(shù)和時間。選關(guān)鍵用于選擇游戲關(guān)數(shù),在游戲過程中這個鍵任何時候都有
111、效,當(dāng)按下選關(guān)鍵后,游戲地圖返回第一關(guān),再次按下時游戲進(jìn)入二關(guān),這樣每按下一次鍵游戲關(guān)數(shù)加一,如果游戲到了第17關(guān)將自動返回第一關(guān)。</p><p> 游戲在主程序中設(shè)了按鍵去抖程序。既在實際當(dāng)中由于偶然的原因鍵盤抖動而導(dǎo)致引腳電平為低人后瞬間又恢復(fù)為高,或雖然只是按下按鍵一次然后放掉,結(jié)果在按鍵信號穩(wěn)定前后,竟出現(xiàn)了一些不該存在的噪聲,這些情況下按鍵是并沒有真的被按下的,如果沒有去抖動程序,游戲會將其當(dāng)做一次
112、正確的按鍵操作去執(zhí)行相應(yīng)功能,這樣就會引起電路的誤動作。處理方法是:當(dāng)掃描到有鍵按下時,軟件演示10ms在判斷改鍵時候仍是按鍵,若是這按鍵有效,同時喇叭發(fā)聲,否則,把它當(dāng)成是誤操作處理。這樣大大提高了程序的可靠性。</p><p> 本游戲還是有一些不足之處,比如沒有設(shè)置超時提示、游戲地圖界面比較小,最大的地圖也只有8行9列,對于一些大的地圖無法顯示、游戲發(fā)聲也比較單調(diào),只有一個頻率的聲音、雖然代碼幾經(jīng)修改也難
113、免有不足之處,代碼的優(yōu)化程度可能是個問題,要知道代碼越多單片機執(zhí)行速度就越慢,依靠提高晶振頻率來提高速度是不能解決問題的實質(zhì)的。沒修改之前代碼長度至少多出現(xiàn)在一半,但我不能說現(xiàn)在的就是最精煉的,可能有待改進(jìn)的地方還很多。</p><p> 在沒有優(yōu)化代碼之前數(shù)據(jù)代碼段的128字節(jié)存儲區(qū)遠(yuǎn)遠(yuǎn)不夠,當(dāng)時我考慮外部擴展數(shù)據(jù)存儲區(qū),但那樣一來不僅電路復(fù)雜,且程序長度和讀寫速度都受到影響,幾經(jīng)修改終于將數(shù)據(jù)區(qū)壓縮到101
114、.3字節(jié),省去了外部數(shù)據(jù)存取器使電路變得更加簡潔, 同時也降低控制器的成本。</p><p><b> 5 總結(jié)</b></p><p> 在這段設(shè)計的過程中,確實也遇到很多的困難。首先,第一次獨立完成這樣的畢業(yè)設(shè)計,開始的時候不知從何下手,沒有頭緒,這是讓我最頭痛的事情。其次用單片機邊游戲是一個不常見的課題,這方面的資料不是很多,所有的一切只有靠自己去摸索,這是
115、一個比較漫長的過程。在求助于老師、理清思路后,于是到圖書館、網(wǎng)上查閱資料,終于攻克畢業(yè)設(shè)計中的道道難題。其中繪制電路原理圖、編程是考驗我的一道難題。經(jīng)過指導(dǎo)老師楊老師的耐心指點和連續(xù)一個星期的奮戰(zhàn)才算基本合格。隨后畫電路圖,寫程序,仿真都沒少讓我傷透腦筋。但是,當(dāng)我把這些問題都解決后,我發(fā)現(xiàn)我收獲了不少,通過查資料讓我了解了直流電機工作原理及用途、PWM控制技術(shù)、鍵盤電路接口技術(shù)、時鐘電路技術(shù)等等,同時也讓我學(xué)習(xí)現(xiàn)代電子產(chǎn)品的設(shè)計流程,
116、為以后從事產(chǎn)品開發(fā)打好了基礎(chǔ)。</p><p> 雖然我的這次論文作品并不是很完善,還有很多的不足之處,但是我仍可以肯定地說,這里面的每一個圖、每一個字,都是經(jīng)過我的大腦篩選出來的。當(dāng)看著自己排好的版面符合設(shè)計的要求,自己編寫的程序能夠按照設(shè)計的要求正常運行時,心里多少有點成就感和欣慰。我相信在這設(shè)計過程中的所有酸甜苦辣最終都會化為甜美的甘泉。</p><p> 這次做畢業(yè)設(shè)計的經(jīng)歷也
117、會使我受益匪淺。我認(rèn)為不管做畢業(yè)設(shè)計也好,還是做其他什么樣的事也好,都要努力去做,還要用心去學(xué),更要有堅持不懈的精神,只有這樣才能收獲到最好的果實。</p><p><b> 參考文獻(xiàn):</b></p><p> 1任治剛.《電子信息工程專業(yè)英語教程》[M]北京.電子工業(yè)出版社.2006.129-15</p><p> 2 張萬奎.《模擬
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 畢業(yè)論文----基于單片機的推箱子游戲設(shè)計
- 畢業(yè)設(shè)計(論文)基于單片機的推箱子游戲設(shè)計
- 基于android的推箱子游戲設(shè)計畢業(yè)論文
- 基于android的推箱子游戲的設(shè)計畢業(yè)論文
- 基于android推箱子游戲的設(shè)計與實現(xiàn)畢業(yè)論文
- 【畢業(yè)設(shè)計論文】基于c語言推箱子游戲設(shè)計畢業(yè)論文
- 畢業(yè)論文基于單片機的時鐘設(shè)計
- 單片機畢業(yè)論文--基于單片機的led顯示屏設(shè)計
- 基于j2me手機推箱子游戲的設(shè)計與實現(xiàn)[畢業(yè)論文]
- 51單片機畢業(yè)論文---基于單片機的進(jìn)制換算
- 基于單片機的畢業(yè)論文-- 基于51單片機的搶答器設(shè)計
- 基于單片機的畢業(yè)論文-- 基于51單片機的搶答器設(shè)計
- 基于51單片機模擬射擊類游戲畢業(yè)論文
- 基于單片機實現(xiàn)的俄羅斯方塊游戲畢業(yè)論文
- 基于單片機數(shù)字電源設(shè)計畢業(yè)論文
- 基于單片機實現(xiàn)的俄羅斯方塊游戲-畢業(yè)論文
- 基于單片機實現(xiàn)的俄羅斯方塊游戲-畢業(yè)論文
- 畢業(yè)論文——基于單片機實現(xiàn)的俄羅斯方塊游戲
- 畢業(yè)論文基于單片機的光立方設(shè)計
- 畢業(yè)論文---基于單片機的智能血壓設(shè)計
評論
0/150
提交評論