找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 12830|回復: 20
打印 上一主題 下一主題
收起左側

DIY復古掌上像素游戲機(2個8*8點陣屏)童年記憶 附單片機源碼

  [復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:287429 發(fā)表于 2018-3-4 15:02 來自手機 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式


電路原理圖:

這個剛開始的原型只是一條蛇。。
所謂一百個程序員有一百條蛇,剛開始我只是想把我之前用C語言寫的貪吃蛇程序拿到單片機,在8*8的點陣跑一下,但覺得有點簡單,在STC12C5A60S2單片機下只用了不到程序10%覺得還是加點什么的,后來就加了俄羅斯方塊,賽車,打飛機。。索性做了個簡易的GUI界面。
硬件結構非常簡單,用了一個逆天IAP15F2K61S2單片機,直接用單片機管腳推挽模式驅(qū)動點陣,限流電阻什么的都不管了,不用任何外圍IC,兩個8*8點陣和三位數(shù)碼管,共用一組數(shù)據(jù)口,幾乎用了單片機所以引腳;采用逐點掃描方式,并且用軟PWM調(diào)節(jié)亮度,媽媽再也不用擔心我單片機電流過載了而燒壞了~
可怕的背部飛線:

較早版本是并口數(shù)據(jù)模式,走線比較痛苦,但程序比較好寫,
后面版本修改了驅(qū)動,引腳可以自由映射,走線起來就很舒服了。
實現(xiàn)同一屏,不同對比度:





大概4~5天之后來了,這個快遞包裹體積很小,但重量異常的沉。。。


焊上元件,燒上程序,還好能正常運行,總算松了口氣。。。。


看著心好累,焊得我蛋疼。。。



/******************************************************************************************************/
目前有四款游戲程序空間大概用了40%左右,后續(xù)有時間精力更新更多的游戲進來。。
以下是工程文件,如果你有單片機基礎,那就自己也DIY一個吧,回味下童年。
/****************************************工程文件下載區(qū)*******************************************/

視頻:


單片機源程序如下:
  1. /*
  2. //作者:鄭梓濱        Jaupin@126.com
  3. //功能:復古掌上俄羅斯方塊游戲機源代碼,包括游戲GUI,俄羅斯方塊、貪吃蛇、經(jīng)典賽車游戲、射擊障礙物游戲
  4. v1.0:
  5.         2014-7-26 00:00:00        :完成有俄羅斯方塊游戲基本模型;
  6.         2014-7-28 02:12:03        :將原先臨時使用的延時鍵盤掃描改為外部中斷狀態(tài)位檢測鍵;
  7.         2014-7-28 20:40:37        :完成俄羅斯方塊分數(shù)計數(shù)及分數(shù)顯示功能;
  8.         2014-8-1 01:01:54        :將較早之前完成貪吃蛇游戲代碼合并植入;
  9.         2014-8-2 17:04:25        :整理之前的臨時源碼,使工程文件規(guī)范化;
  10.         2014-8-3 23:50:49        :構建游戲選擇畫面基本模型,完成畫面平移效果;
  11.         2014-8-5 00:50:04        :改進LED點陣底層驅(qū)動,用軟件PWM調(diào)節(jié)畫面亮度;
  12.         2014-8-7 00:53:35        :完成賽車游戲,用PWM分層掃描畫面,形成游戲畫面對比度;
  13.         2014-8-8 02:16:44        :完成賽車游戲選擇預覽畫面,并將三個游戲合并在一起;
  14.         2014-8-12 01:47:07        :將逐行掃描改為逐點掃描,使顯示亮度均勻;增加亮度調(diào)節(jié)功能;
  15.         2014-9-9 00:32:40        :修改及優(yōu)化若干細節(jié);
  16. v1.1:
  17.         2014-9-18 0:57:23        :重新布局電路,修改原先不合理的地方,為制作PCB板作準備;
  18.         2014-9-19 22:02:36        :加入游戲音效,并且可以通過軟件方式開關聲音;
  19.         2014-9-21 14:59:39        :增加三位mini數(shù)碼管,實時顯示游戲分數(shù),數(shù)碼管共用點陣并行數(shù)據(jù)口;
  20.         ~~~~~~~~~~~忘記備注
  21.         2014-10-20 21:30:15        :加入射擊游戲,將GUI模塊化,簡化流程
  22. */

  23. #include "config.h"
  24. volatile uint8 data keypad = K_NULL;        //鍵盤狀態(tài)
  25. volatile uint8 data keycont = 0;                //鍵盤檢測消抖定時器
  26. volatile uint16 data tms = 0;                        //1ms T0定時器
  27. bit key_state = 0;                                                //按鍵狀態(tài)

  28. uint16 data speeds = 0;                //游戲速度
  29. uint16 data scores = 0;                //游戲計分
  30. bit Glife = 1;                                //游戲生命
  31. bit sound_ON = 1;                        //音效開關
  32. uint8 data duty = 80;                //PWM,默認亮度
  33. uint8 data DispRAM[16]={0};
  34. uint8 code bitman[8]={1,2,4,8,16,32,64,128};//用于數(shù)字序號定位0~7bit位

  35. uint8 code num[10][5]=                //陽碼
  36. {
  37.         {0x7,0x5,0x5,0x5,0x7},
  38.         {0x2,0x6,0x2,0x2,0x7},
  39.         {0x7,0x1,0x7,0x4,0x7},
  40.         {0x7,0x1,0x7,0x1,0x7},
  41.         {0x5,0x5,0x7,0x1,0x1},
  42.         {0x7,0x4,0x7,0x1,0x7},
  43.         {0x7,0x4,0x7,0x5,0x7},
  44.         {0x7,0x1,0x1,0x1,0x1},
  45.         {0x7,0x5,0x7,0x5,0x7},
  46.         {0x7,0x5,0x7,0x1,0x7}
  47. };

  48. /*********************PORT_INIT********************/
  49. void Port_Init()
  50. {
  51.         P0M0 = 0Xff;
  52.         P0M1 = 0X00;
  53.         P1M0 = 0Xff;
  54.         P1M1 = 0X00;
  55.         P2M0 = 0Xff;
  56.         P2M1 = 0X00;
  57.         P3M0 = 0X00;
  58.         P3M1 = 0X00;
  59.         P4M0 = 0Xff;
  60.         P4M1 = 0X00;
  61.         P5M0 = 0Xff;
  62.         P5M1 = 0X00;
  63. }

  64. void Init_Timer()
  65. {
  66. /******************定時器0中斷設置**********************/
  67.         AUXR |= 0x80;                   //定時器0為1T模式
  68.     TMOD = 0x00;                    //設置定時器為模式0(16位自動重裝載)
  69.     TL0 = T1MS;                     //初始化計時值
  70.     TH0 = T1MS >> 8;
  71.     TR0 = 1;                        //定時器0開始計時
  72.     ET0 = 1;                        //使能定時器0中斷
  73.        
  74. /*****************外部中斷設置*************************/       
  75.         IT0 = 1;                    //設置INT0下降沿觸發(fā)
  76.     EX0 = 1;                    //使能外部中斷INT0
  77.         IT1 = 1;                    //設置INT1下降沿觸發(fā)
  78.     EX1 = 1;                    //使能外部中斷INT1
  79.         INT_CLKO |= 0x70;           //使能INT2,INT3,INT4(EX4 = 1,EX3 = 1,EX2 = 1
  80.        
  81.         EA = 1;       
  82. }

  83. void Array_CLR(uint8 *p)
  84. {
  85.         uint8 i=0;
  86.         while(i!=16)
  87.         {
  88.                 p[i] = 0x00;
  89.                 i++;
  90.         }
  91. }

  92. void ShowScore(uint score)
  93. {
  94.         uint8 i;
  95.         uint8 qx,bx,sx,gx;
  96.         qx = score /1000;
  97.         bx = score %1000 /100;
  98.         sx = score %100/10;
  99.         gx = score %10;

  100.         Array_CLR(DispRAM);

  101.         for(i=0;i<5;i++)
  102.                 DispRAM[8-i] = (num[sx][i]<<4) | (num[gx][i]);
  103.        
  104.         for(i=0;i<5;i++)
  105.                 DispRAM[14-i] = (num[qx][i]<<5) | (num[bx][i]<<1);
  106.                                
  107. //        MatxDisp(DispRAM,duty);
  108. }

  109. void main()
  110. {
  111.         Port_Init();
  112.         Sound_Init();
  113.         Init_Timer();
  114.         Sound_Tone(1,14,5);//滴
  115.        
  116.         srand(TL0);               
  117.         delayms(100);
  118.         Play_Music(sound_game_start);
  119.         Flash_Screen_Clear();
  120.         while(1)
  121.         {
  122.                 tms = 0;
  123.                 keypad = K_NULL;//清除按鍵狀態(tài)
  124.                 switch (GUI_Main())        //進入用戶游戲選擇界面,返回選擇的游戲
  125.                 {
  126.                         case 1:        Tetris_Game();        break;
  127.                         case 2:        Snake_Game();        break;
  128.                         case 3:        RAC_Game();                break;
  129.                         case 4:        Shot_Game();        break;
  130.                 }
  131.                 Play_Music(sound_game_over);
  132.                 Flash_Screen_Clear();
  133.                 ShowScore(scores);        //將分數(shù)載入顯存
  134.                 delayms(300);
  135.                
  136.                 keypad = K_NULL;
  137.                 while(keypad != K_UP)        //在沒按下OK鍵時保持分數(shù)顯示
  138.                 {
  139.                         MatxDisp(DispRAM,duty);
  140.                         SMG_Display(scores,duty);
  141.                 }
  142.         }       
  143. }

  144. /* Timer0 interrupt routine */
  145. void T0_Timer_1ms_int() interrupt 1 using 1
  146. {
  147.         if(tms<0xfffe)        tms++;        //防止溢出
  148.         if(key_state){ if(!--keycont) key_state=0;}

  149.         if(PIN_TR2)//TR2如果打開,則開始播放音效
  150.         {
  151.                 if(!sound_cnt_time--)
  152.                 {
  153.                         TR2_OFF;
  154.                         beep = 1;
  155.                         if(music_p[s_p][1])
  156.                         {
  157.                                 Sound_Tone(sound_ON,music_p[s_p][0],music_p[s_p][1]);
  158.                                 s_p++; //自動裝載下一個音符,實現(xiàn)音效與游戲“同時”運行
  159.                         }
  160.                 }
  161.         }
  162.         if(KEY_DOWN==0 & KEY_UP==0)        IAP_CONTR=0x60;//軟件復位下載程序
  163. }

  164. void T2_Timer_Sound_freq() interrupt 12           //中斷入口
  165. {
  166.      beep = ~beep; //蜂鳴器頻率震動
  167. }

  168. uint8 Get_Kvuale(uint8 key_delay)//鍵值消抖處理,參數(shù)為靈敏度調(diào)節(jié)
  169. {
  170.         uint8 kvuale = K_NULL;        //返回的初始值為空值
  171.         if(keypad != K_NULL)        //當鍵值不為NULL時,說明有按鍵按下
  172.         {       
  173.                 if(!key_state)                //當按鍵狀態(tài)位state為0時說明是第一次觸發(fā)有效,為1時為重復觸發(fā)
  174.                 {
  175.                         key_state=1;        //置1,防止重復觸發(fā)
  176.                         kvuale = keypad;//獲得讀取鍵值
  177.                         keycont = key_delay;//載入消抖時間
  178.                 }
  179.                 keypad = K_NULL;        //清楚鍵值
  180.         }
  181.         return kvuale;
  182. }
  183. /*********外部中斷按鍵區(qū)**********/
  184. void exint0() interrupt 0       //INT0
  185. {
  186.         keypad = 0;
  187. }
  188. void exint1() interrupt 2       //INT1
  189. {
  190.         keypad = 1;       
  191. }
  192. void exint2() interrupt 10      //INT2
  193. {
  194.         keypad = 2;
  195. }
  196. void exint3() interrupt 11      //INT3
  197. {
  198.         keypad = 3;
  199. }
  200. void exint4() interrupt 16      //INT4
  201. {       
  202. ……………………

  203. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
原理圖及源代碼: GAMEBOX_CODE_Keil5_v1.1.zip (291.3 KB, 下載次數(shù): 145)
環(huán)境:Keil4/keil5
PCB工程文件: 復古掌上游戲機工程文件.zip (2.39 MB, 下載次數(shù): 86)
繪制軟件:Altium Designer Winter 09
(說明:PCB工程文件中的布線是源碼中的默認配置,使用直插封裝DIY制作需要修改config.h文件定義引腳。)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏10 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發(fā)
ID:287429 發(fā)表于 2018-3-4 15:04 來自手機 | 只看該作者
圖不見了

34a567cf3bc79f3def81456fb9a1cd11738b29a1.jpg (52.96 KB, 下載次數(shù): 164)

34a567cf3bc79f3def81456fb9a1cd11738b29a1.jpg

9a91de3d70cf3bc789606cb3d200baa1cc112aa1.jpg (87.52 KB, 下載次數(shù): 149)

9a91de3d70cf3bc789606cb3d200baa1cc112aa1.jpg

82a67009c93d70cf2e9a0b52fbdcd100bba12ba1.jpg (76.95 KB, 下載次數(shù): 159)

82a67009c93d70cf2e9a0b52fbdcd100bba12ba1.jpg
回復

使用道具 舉報

板凳
ID:287429 發(fā)表于 2018-3-4 15:21 來自手機 | 只看該作者
怎么上傳
回復

使用道具 舉報

地板
ID:313960 發(fā)表于 2018-5-10 22:46 | 只看該作者
好想學一學,做一做,覺得好復雜好難的樣子。。。
回復

使用道具 舉報

5#
ID:161343 發(fā)表于 2018-5-11 16:23 | 只看該作者
點陣是什么型號的啊樓主
回復

使用道具 舉報

6#
ID:378221 發(fā)表于 2018-7-24 01:28 | 只看該作者
路過幫頂
回復

使用道具 舉報

7#
ID:294331 發(fā)表于 2018-7-27 17:44 | 只看該作者
感謝樓主分享,樓主很厲害哦
回復

使用道具 舉報

8#
ID:179958 發(fā)表于 2018-7-28 13:52 來自手機 | 只看該作者
666,有空也做個
回復

使用道具 舉報

9#
ID:479299 發(fā)表于 2019-2-22 16:01 | 只看該作者
mark,回頭學習
回復

使用道具 舉報

10#
ID:401370 發(fā)表于 2019-3-4 14:14 | 只看該作者
兩個點陣是怎么連接的呀?
回復

使用道具 舉報

11#
ID:1091354 發(fā)表于 2023-8-15 11:08 | 只看該作者
學習學習也是不錯的。
回復

使用道具 舉報

12#
ID:59884 發(fā)表于 2023-8-18 13:16 | 只看該作者
謝謝樓主分享!有空也做個來玩。
回復

使用道具 舉報

13#
ID:71233 發(fā)表于 2023-8-18 18:40 | 只看該作者
請問不同亮度是怎樣實現(xiàn)的?
回復

使用道具 舉報

14#
ID:77589 發(fā)表于 2023-11-1 14:38 | 只看該作者
lmn2005 發(fā)表于 2023-8-18 18:40
請問不同亮度是怎樣實現(xiàn)的?

行或列停留時間長度
回復

使用道具 舉報

15#
ID:899981 發(fā)表于 2023-11-2 10:58 | 只看該作者
移動咋搞的?另外咋知道插入了?
回復

使用道具 舉報

16#
ID:998401 發(fā)表于 2023-11-2 11:21 | 只看該作者
學習準備做一個
感謝樓主
回復

使用道具 舉報

17#
ID:157007 發(fā)表于 2023-12-28 22:02 | 只看該作者
ZHAOBAO511 發(fā)表于 2023-11-2 10:58
移動咋搞的?另外咋知道插入了?

二維數(shù)組,圖像移動就是里面的數(shù)字的行和列在改變。
不斷查詢同一行是否全是一,如果是,則消去,上方的自動下落。

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

18#
ID:965040 發(fā)表于 2024-1-9 08:44 | 只看該作者
學習了, 文件很詳細,贊
回復

使用道具 舉報

19#
ID:86633 發(fā)表于 2024-6-12 14:47 | 只看該作者
學習一下,支持下
回復

使用道具 舉報

20#
ID:60122 發(fā)表于 2024-6-23 10:49 | 只看該作者
某寶上 好多這個賣 是不是抄的樓主的
回復

使用道具 舉報

21#
ID:46004 發(fā)表于 2024-10-18 17:39 | 只看該作者

學習準備做一個
感謝樓主
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表