久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

51單片機8x8點陣貪食蛇游戲機程序,支持投幣檢測、上位機、最高分記錄等功能

[復制鏈接]
跳轉到指定樓層
樓主
好久不寫51單片機了,最近做了一個貪食蛇游戲機。


用到的模塊包括:8x8點陣,LCD1602,矩陣鍵盤、紅外遙控器、光敏電阻、EEPROM、電機驅動等
實現的功能包括:投幣檢測,紅外、鍵盤、上位機三種操作模式、最高分記錄、震動反饋等

在B站傳了一個驗收時候的視頻,所有的功能的介紹都在視頻里強烈建議直接戳視頻看
強烈建議直接戳視頻看
強烈建議直接戳視頻看:
https://www.bilibili.com/video/BV1Ba4y1Y7oz?share_source=copy_web
上位機界面:



51是用keil建的工程,上位機是QT寫的。附件包含了全部的代碼,51和上位機都有嗷~



單片機源程序如下:
  1. #include <reg52.h>
  2. #include "typedef.h"
  3. #include "LCD1602.h"
  4. #include "LED88.h"
  5. #include "key.h"
  6. #include "IR.h"
  7. #include "24c02.h"
  8. #include "UART.h"
  9. #include "XPT2046.h"

  10. sfr  T2MOD = 0xc9;   //補充寄存器T2MOD定義
  11. sbit motor = P2^2;   //電機接口

  12. u8 time = 0;        //每50ms加一
  13. u8 game_state = 0;  //指示游戲進行狀態
  14. u8 game_level = 1;  //游戲難度等級。每吃到八個點增加一級
  15. u16 ADC_value = 0;  //光敏電阻采值
  16. u8 control_mode = 0;//控制模式,1為板載按鍵,2為紅外遙控
  17. u8 score_record = 0;//最高分記錄,保存在24c02中

  18. extern u8 length;   //蛇身長度
  19. extern u8 direction;//前進方向
  20. extern u8 food_x;   //食物點坐標
  21. extern u8 food_y;
  22. extern u8 xdata snake_x[64];  //蛇身坐標
  23. extern u8 xdata snake_y[64];
  24. extern u8 key_value;    //按鍵操作
  25. extern u8 IR_value;     //紅外遙控按鍵操作
  26. extern u8 irtime;       //紅外遙控計時標志位
  27. extern u8 UART_data;    //串口接收內容

  28. sbit test = P1^1;

  29. void main()
  30. {
  31.         motor = 0;     //關閉電機
  32.         LCD1602_Init();//1602初始化
  33.         I2C_init();    //I2C初始化
  34.         LED88_clean(); //8x8點陣清屏

  35.         //從24C02中讀取游戲最高分記錄
  36.         score_record = I2C_ReceiveData(0);//從AT24C02第0個單元中讀取數據

  37.         //使能定時器2 50ms 用于貪食蛇、LCD閃爍等計時       
  38.         T2MOD = 0;      //向上計數
  39.     T2CON = 0;      //16位自動重裝模式
  40.     TL2 = 0x00;     //設置定時初值
  41.     TH2 = 0x4C;
  42.     RCAP2L = 0x00;  //設置定時重載值
  43.     RCAP2H = 0x4C;
  44.         ET2=1;
  45.         TR2=1;

  46.         //使能總中斷開關
  47.         EA = 1;       
  48.        
  49.         //剛上電時ADC讀值不穩定,延遲2s啟動
  50.         LCD1602_Dis_Str(0, 0, "Welcome!");
  51.                
  52.         while(1)
  53.         {
  54.                 u8 i,last_state,flag;
  55.                
  56.                 test = ~test;
  57.                
  58.                 //模式更新第一次進入while時,flag會被置0
  59.                 if(game_state!=last_state)
  60.                         flag = 0;
  61.                 else
  62.                         flag = 1;
  63.                 last_state = game_state;

  64.                 switch(game_state)
  65.                 {
  66.                         //未開始游戲,需要投幣
  67.                         case 0:
  68.                                 //AD采值要放在LCD刷新之前,否則受引腳共用的影響會出錯
  69.                                 ADC_value = (ADC_read(AD_CH0));

  70.                                 //INSERT COIN每1s閃爍
  71.                                 if(time/20%2==0)
  72.                                         LCD1602_Dis_Str(0, 1, "INSERT COIN");
  73.                                 else
  74.                                         LCD1602_Dis_Str(0, 1, "           ");
  75.                                
  76.                                 //如果光敏被遮住,認為投入硬幣,開始游戲
  77.                                 if(ADC_value>1500)
  78.                                 {
  79.                                         ADC_value = 0;
  80.                                         LCD1602_clean(); //LCD清屏
  81.                                         snake_food();    //隨機初始化一個食物的位置
  82.                                         game_state = 1;  //進入操作方式選擇
  83.                                 }
  84.                                 else
  85.                                         delay_ms(10);  //ADC采值不能過于頻繁,否則會出錯
  86.                         break;
  87.                                
  88.                         //選擇操作方式
  89.                         case 1:
  90.                                 //通過flag變量確保以下內容只執行一次
  91.                                 if(flag==0)
  92.                                 {
  93.                                         LCD1602_Dis_Str(0, 0,  "Select Ctrl Mode");
  94.                                         LCD1602_Dis_Str(0, 1,  "1:Key 2:IR 3:PC");
  95.                                 }
  96.                                
  97.                                 key_scan();        //掃描矩陣鍵盤
  98.                                 if(key_value==16)  //按S2選擇板載鍵盤操作
  99.                                 {
  100.                                         control_mode = 1;
  101.                                         key_value = 0;   //按鍵標志位清零
  102.                                 }
  103.                                 else if(key_value==17)  //按S3選擇紅外遙控器操作
  104.                                 {
  105.                                         control_mode = 2;
  106.                                         key_value = 0;   //按鍵標志位清零
  107.                                        
  108.                                         //使能定時器1 用于紅外遙控
  109.                                         TMOD|= 0x20;
  110.                                         TH1  = 0x00;
  111.                                         TL1  = 0x00;
  112.                                         ET1  = 1;
  113.                                         TR1  = 1;   
  114.                                         //使能外部中斷 用于紅外遙控
  115.                                         IT0 = 1;
  116.                                         EX0 = 1;
  117.                                 }
  118.                                 else if(key_value==18)
  119.                                 {
  120.                                         control_mode = 3;
  121.                                         key_value = 0;   //按鍵標志位清零
  122.                                        
  123.                                         UART_init();
  124.                                 }
  125.                                 if(control_mode!=0)
  126.                                 {
  127.                                         //倒計時三秒開始
  128.                                         LCD1602_clean();
  129.                                         LCD1602_Dis_Str(8, 0, "3");
  130.                                         delay_ms(1000);
  131.                                         LCD1602_Dis_Str(8, 0, "2");
  132.                                         delay_ms(1000);
  133.                                         LCD1602_Dis_Str(8, 0, "1");
  134.                                         delay_ms(1000);
  135.                                        
  136.                                         //LCD清屏,顯示游戲界面信息
  137.                                         LCD1602_clean();
  138.                                         LCD1602_Dis_Str(0, 0,  "level:");
  139.                                         LCD1602_Dis_Str(0, 1,  "score:");
  140.                                        
  141.                                         game_state = 2;  //進入游戲模式                                       
  142.                                         time = 0;       //T0累加位清零
  143.                                 }
  144.                         break;
  145.                        
  146.                         //游戲進行中
  147.                         case 2:                       
  148.                                 //刷新游戲界面
  149.                                 for(i=0; i<length; i++)
  150.                                         LED88_point(snake_x[i], snake_y[i]);  //顯示蛇
  151.                                 LED88_point(food_x, food_y); //顯示食物
  152.                                
  153.                                 //獲取用戶操作
  154.                                 if(control_mode==1)
  155.                                         key_scan();   //掃描矩陣鍵盤
  156.                                 else if(control_mode==2)
  157.                                         IR_process(); //處理紅外遙控
  158. //                                else if(control_mode==3)
  159. //                                        UART_receive();
  160.                                
  161.                                 //手動調節難度等級
  162.                                 if(key_value==18 || IR_value==18 || UART_data==18)
  163.                                 {
  164.                                         key_value = 20;
  165.                                         IR_value  = 20;
  166.                                         UART_data = 20;
  167.                                         if(game_level<9)
  168.                                                 game_level++;
  169.                                         time = 0;
  170.                                 }       
  171.                                 else if(key_value==17 || IR_value==17 || UART_data==17)
  172.                                 {
  173.                                         key_value = 20;
  174.                                         IR_value  = 20;
  175.                                         UART_data = 20;
  176.                                         if(game_level>1)
  177.                                                 game_level--;
  178.                                         time = 0;
  179.                                 }       
  180.                                 //顯示難度等級和得分
  181.                                 LCD1602_Dis_Str(7, 0, u8_to_str(game_level));
  182.                                 LCD1602_Dis_Str(7, 1, u8_to_str((length-3)/10));
  183.                                 LCD1602_Dis_Str(8, 1, u8_to_str((length-3)%10));
  184.                                 //如果打破紀錄,顯示new record字樣
  185.                                 if((length-3)>score_record)
  186.                                 {
  187.                                         LCD1602_Dis_Str(11, 0, "new");
  188.                                         LCD1602_Dis_Str(10, 1, "record");
  189.                                 }
  190.                                 //如果長度達到64,直接結束游戲
  191.                                 if(length==64)
  192.                                 {
  193.                                         LCD1602_clean();
  194.                                         LED88_clean();
  195.                                         game_state = 4;
  196.                                         time = 0;
  197.                                 }
  198.                                 //判斷是否暫停
  199.                                 if(key_value==16 || IR_value==16 || UART_data==16)  //按下暫停鍵
  200.                                 {
  201.                                         LCD1602_clean();
  202.                                         LCD1602_Dis_Str(0, 0,  "-----Pause-----");
  203.                                         game_state = 3;
  204.                                         key_value = 20;     //清空按鍵值,否則會直接觸發繼續
  205.                                         IR_value  = 20;
  206.                                         UART_data = 20;
  207.                                 }
  208.                         break;
  209.                        
  210.                         //游戲暫停
  211.                         case 3:
  212.                                 ET0 = 0;  //關閉T0,蛇保持靜止
  213.                        
  214.                                 //刷新游戲界面
  215.                                 for(i=0; i<length; i++)
  216.                                         LED88_point(snake_x[i], snake_y[i]);  //顯示蛇
  217.                                 LED88_point(food_x, food_y); //顯示食物
  218.                        
  219.                                 //獲取用戶操作
  220.                                 if(control_mode==1)
  221.                                         key_scan();   //掃描矩陣鍵盤
  222.                                 else if(control_mode==2)
  223.                                         IR_process(); //處理紅外遙控
  224. //                                else if(control_mode==3)
  225. //                                        UART_receive();
  226.                        
  227.                                 //判斷是否繼續
  228.                                 if(key_value==16 || IR_value==16 || UART_data==16)   //按下繼續鍵
  229.                                 {
  230.                                         LCD1602_clean(); //LCD清屏,顯示游戲信息
  231.                                         LCD1602_Dis_Str(0, 0,  "level:");
  232.                                         LCD1602_Dis_Str(0, 1,  "score:");
  233.                                         key_value = 20;  //清空按鍵值,否則會直接觸發繼續
  234.                                         IR_value  = 20;
  235.                                         UART_data = 20;
  236.                                         game_state = 2;  //回到游戲狀態(2)
  237.                                         TH0 = 0x4C;
  238.                                         TL0 = 0x00;
  239.                                         ET0 = 1;
  240.                                         time = 0;
  241.                                 }               
  242.                         break;

  243.                         //死亡
  244.                         case 4:
  245.                                 //如果沒有打破紀錄
  246.                                 if((length-3)<=score_record)
  247.                                 {
  248.                                         //GAME OVER閃爍
  249.                                         if(time/20%2==0)
  250.                                                 LCD1602_Dis_Str(0, 0, "GAME OVER");
  251.                                         else
  252.                                                 LCD1602_Dis_Str(0, 0, "         ");       
  253.                                        
  254.                                         //通過變量flag使得以下內容只執行一次
  255.                                         if(flag==0)
  256.                                         {
  257.                                                 LCD1602_clean();
  258.                                                 LED88_clean();
  259.                                                 //顯示得分
  260.                                                 LCD1602_Dis_Str(0,  1, "Your score:");
  261.                                                 LCD1602_Dis_Str(11, 1, u8_to_str((length-3)/10));
  262.                                                 LCD1602_Dis_Str(12, 1, u8_to_str((length-3)%10));
  263.                                         }
  264.                                 }
  265.                                 //如果打破紀錄
  266.                                 else
  267.                                 {
  268.                                         //通過變量flag使得以下內容只執行一次
  269.                                         if(flag==0)
  270.                                         {
  271.                                                 LCD1602_clean();
  272.                                                 LED88_clean();
  273.                                                 //將新紀錄保存至24c02
  274.                                                 I2C_TransmitData(0, length-3);
  275.                                                 //顯示得分
  276.                                                 LCD1602_Dis_Str(0,  1, "New record:");
  277.                                                 LCD1602_Dis_Str(11, 1, u8_to_str((length-3)/10));
  278.                                                 LCD1602_Dis_Str(12, 1, u8_to_str((length-3)%10));
  279.                                         }
  280.                                         //CONGRATULATIONS!閃爍
  281.                                         if(time/20%2==0)
  282.                                                 LCD1602_Dis_Str(0, 0, "CONGRATULATIONS!");
  283.                                         else
  284.                                                 LCD1602_Dis_Str(0, 0, "                ");
  285.                                 }
  286.                                 //按S5可以清除最高分記錄
  287.                                 key_scan();
  288.                                 if(key_value==19)
  289.                                 {
  290.                                         I2C_TransmitData(0, 0);
  291.                                         score_record = 0;
  292.                                         LCD1602_clean();
  293.                                         LCD1602_Dis_Str(0, 0, "Reset complete");
  294.                                        
  295.                                         key_value = 20;
  296.                                         delay_ms(1000);
  297.                                         time = 200; //清除完之后延遲一秒直接退回到投幣界面
  298.                                 }
  299.                                 if(time==200)
  300.                                 {
  301.                                         LCD1602_clean();
  302.                                         LCD1602_Dis_Str(0, 0, "Welcome!");
  303.                                         score_record = length-3;
  304.                                         control_mode = 0;
  305.                                         game_state = 0;
  306.                                         game_level = 1;
  307.                                         length = 3;
  308.                                         direction = 4;
  309.                                         snake_x[0] = 2;
  310.                                         snake_x[1] = 1;
  311.                                         snake_x[2] = 0;
  312.                                         snake_y[0] = 0;
  313.                                         snake_y[1] = 0;
  314.                                         snake_y[2] = 0;
  315.                                         delay_ms(100);
  316.                                 }
  317.                         break;       
  318.                 }       
  319.         }
  320. }

  321. //定時器0中斷服務函數
  322. //void timer0_ISR(void) interrupt 1
  323. //{

  324. //}

  325. //定時器1中斷服務函數
  326. void timer1_ISR(void) interrupt 3
  327. {
  328.         irtime++;  //用于計數2個下降沿之間的時間
  329. }

  330. //定時器2中斷服務函數
  331. void timer2_ISR(void) interrupt 5
  332. {
  333.         TF2 = 0;  //T2需要手動清除標志位
  334.        
  335.         time++;
  336.         if(time==255)
  337.                 time = 0;

  338.         if(time==(18-game_level) && game_state==2)
  339.         {
  340.                 time = 0;
  341.                 //計算移動
  342.                 snake_move();
  343.                 //判斷是否吃到食物
  344.                 snake_grow();
  345.                 //吃一個食物點一盞LED
  346.                 P1 = 0xff>>((length-3)%8);
  347.                 //判斷是否死亡
  348.                 snake_death();               
  349.         }
  350. }

  351. //外部中斷0服務函數
  352. void EX0_ISR(void) interrupt 0
  353. {
  354.         IR_interrupt_process();
  355. }
復制代碼

所有資料51hei提供下載:
51單片機貪食蛇.rar (18.36 MB, 下載次數: 32)



評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产一区二区电影网 | 欧美一级欧美三级在线观看 | 免费看国产a | 精品美女久久久久久免费 | 久久99视频这里只有精品 | 中文字幕在线一区 | 亚洲一区久久 | 91精产国品一二三区 | 天堂av在线影院 | 81精品国产乱码久久久久久 | 日本一区二区在线视频 | 精品久久一区 | 欧美一区二区三区在线观看视频 | 日本精品一区二区在线观看 | 国产一级在线观看 | 91亚洲精华国产 | 欧美日韩在线成人 | 日韩免费在线视频 | 欧美天堂在线观看 | 亚洲国产一区二区视频 | 国产成人精品综合 | 精品产国自在拍 | 丝袜 亚洲 欧美 日韩 综合 | 国产一级一级 | 亚洲国产成人精品久久 | 一区二区免费 | 精品一区二区视频 | 少妇诱惑av | 91在线网站| 久久精品手机视频 | 日韩电影一区二区三区 | 国产精品一区二区三区在线 | 日韩无 | 黄网站免费观看 | 欧美日韩国产在线观看 | 国产精品一区二区在线 | 午夜在线观看视频 | 2020国产在线 | 久久综合av| 日韩欧美一区二区三区四区 | 色播99|