前言
隨著科學(xué)技術(shù)的不斷進(jìn)步,嵌入式近些年來逐漸興起,其領(lǐng)域比較新,發(fā)展非常迅速,由于它屬于新興領(lǐng)域,接觸的人并不是很多,但是嵌入式在各種電子設(shè)備上的應(yīng)用越來越越廣泛,并且各種電子設(shè)備也在朝著嵌入式微系統(tǒng),智能化的方向前進(jìn)。STM32系列是基于專為要求高性能、低成本、低功耗的嵌入式應(yīng)用專門設(shè)計的ARM Cortex-M內(nèi)核。作為21世紀(jì)的人才,為了與社會實際需要相銜接,提高我們的學(xué)習(xí)興趣,利用STM32系列單片機(jī)進(jìn)行了一次嵌入式系統(tǒng)設(shè)計。
摘要
在本次作業(yè)中采用STM32系列中的STM32F103RCT6微控制器芯片,采用ALIENTEK戰(zhàn)艦STM32開發(fā)板,使用MiniSTM32開發(fā)板上的 LCD 接口,來點亮 TFTLCD,實現(xiàn)觸摸屏功能。
本次的課程設(shè)計目的是實現(xiàn)一個經(jīng)典的貪吃蛇游戲,整個游戲?qū)崿F(xiàn)功能分別為: 1、初始化程序。 2、隨機(jī)紅點、左轉(zhuǎn)、右轉(zhuǎn)、判斷邊框。 硬件設(shè)計原理圖 根據(jù)此硬件設(shè)計圖再結(jié)合軟件設(shè)計就能做出此游戲。 此次的課程設(shè)計在于開發(fā)個貪吃蛇游戲,其流程圖如下圖所示。 程序流程圖為方便介紹,此軟件實現(xiàn)只給出主要程序部分: 1、本例程提供了硬件平臺的初始化 GPIO是常規(guī)輸入/輸出端口,STM32F103RCT6有PA、PB、PC、PD、PE共5個16位的GPIO。STM32的GPIO都可編程,具有很多復(fù)用功能。GPIO可以配置為很多總模式,這些模式有:輸入浮空、輸入上拉、輸入下拉、模擬輸入、開漏輸入、推挽輸出、推挽復(fù)用、開漏復(fù)用。通過對GPIO寄存器編程,可以設(shè)置每個端口的工作模式。 24C02 EEPROM是開發(fā)板板載的 2Kbit(256 個字節(jié))EEPROM ,型號為:24C02,用于掉電數(shù)據(jù)保存。因為 STM32 內(nèi)部沒有 EEPROM,所開發(fā)板外擴(kuò)了24C02,用于存儲重要數(shù)據(jù),用來做IIC 實驗,該芯片直接掛在 STM32 的 IO 口上。 IIC(Inter-Integrated Circuit)總線是一種由 PHILIPS 公司開發(fā)的兩線式串行總線,用于連接微控制器及其外圍設(shè)備。 它是由數(shù)據(jù)線 SDA 和時鐘 SCL 構(gòu)成的串行總線, 可發(fā)送和接收數(shù)據(jù)。在 CPU 與被控 IC 之間、IC 與 IC 之間進(jìn)行雙向傳送,高速 IIC 總線一般可達(dá) 400kbps 以上。IIC 總線在傳送數(shù)據(jù)過程中共有三種類型信號, 它們分別是:開始信號、結(jié)束信號和應(yīng)答信號。 開始信號:SCL 為高電平時,SDA 由高電平向低電平跳變,開始傳送數(shù)據(jù)。 結(jié)束信號:SCL 為高電平時,SDA 由低電平向高電平跳變,結(jié)束傳送數(shù)據(jù)。 應(yīng)答信號: 接收數(shù)據(jù)的 IC 在接收到 8bit 數(shù)據(jù)后, 向發(fā)送數(shù)據(jù)的 IC 發(fā)出特定的低電平脈沖,表示已收到數(shù)據(jù)。CPU 向受控單元發(fā)出一個信號后,等待受控單元發(fā)出一個應(yīng)答信號,CPU 接收到應(yīng)答信號后,根據(jù)實際情況作出是否繼續(xù)傳遞信號的判斷。若未收到應(yīng)答信號,由判斷為受控單元出現(xiàn)故障。
- /********************************************************************
- * 名 稱:AT24CXX_Init(void)
- * 功 能:初始化IIC接口
- ********************************************************************/
- //初始化IIC接口
- void AT24CXX_Init(void)
- {
- IIC_Init();
- }
- void IIC_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- //RCC->APB2ENR|=1<<4;//先使能外設(shè)IO PORTC時鐘
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
-
- IIC_SCL=1;
- IIC_SDA=1;
-
- }
- /*******************************************************************
- * 名 稱:void CMLCD_Init(void)
- * 功 能:初始化觸摸屏的硬件接口
- ********************************************************************/
- void CMLCD_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能PORTC時鐘
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_3|GPIO_Pin_13;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //設(shè)置成推免輸出
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC 0 3 13
-
- GPIO_InitStructure.GPIO_Pin =GPIO_Pin_2|GPIO_Pin_1; //初始化GPIOC 2 1
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空輸入
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- TPEN=1;
- }
復(fù)制代碼
2、貪吃蛇功能控制
SPI是串行外設(shè)端口,是一種同步串行外設(shè)端口,它可以使MCU與各種外圍設(shè)備以串行方式進(jìn)行通信、交換信息。STM32的SPI支持全雙工同步傳輸,可選擇以8或16位傳輸幀格式進(jìn)行傳輸,支持多種模式。
USART為STM32的同步異步接收器。它提供了一種靈活的方法與使用異步串行數(shù)據(jù)格式的外部設(shè)備之間進(jìn)行全雙工數(shù)據(jù)交換。USART利用分?jǐn)?shù)波特率發(fā)生器提供寬范圍的波特率選擇。另外,它還允許多處理器通信。USART也可以使用DMA方式直接將接受的數(shù)據(jù)存儲到內(nèi)存或從內(nèi)存中批量發(fā)送數(shù)據(jù),也支持多種中斷方式。
TFT-LCD 即薄膜晶體管液晶顯示器。其英文全稱為:Thin Film Transistor-Liquid CrystalDisplay。TFT-LCD 與無源 TN-LCD、STN-LCD 的簡單矩陣不同,它在液晶顯示屏的每一個象素上都設(shè)置有一個薄膜晶體管(TFT) ,可有效地克服非選通時的串?dāng)_,使顯示液晶屏的靜態(tài)特性與掃描線數(shù)無關(guān),因此大大提高了圖像質(zhì)量。TFT-LCD 也被叫做真彩液晶顯示器。ALIENTEK 提供的 2.8寸TFTLCD 模塊,其驅(qū)動芯片有很多種類型,比如有:ILI9341/ILI9325/RM68042/RM68021/ILI9320/ILI9328/LGDP4531/LGDP4535/SPFD5408/SSD1289/1505/B505/C505/NT35310/NT35510 等。
LED(DS0 和 DS1)。其電路在ALIENTEK MiniSTM32開發(fā)板上默認(rèn)是已經(jīng)連接好了的。DS0接PA8,DS1接PD2。
- 系統(tǒng)調(diào)試及實驗結(jié)果
調(diào)試過程: 在測試過程中出現(xiàn)了一些問題,點觸的時候點不準(zhǔn)確,我覺得可以加上觸屏校準(zhǔn),使其精準(zhǔn)。 實驗結(jié)果: 達(dá)到隨機(jī)生成果實、蛇上下左右移動、判斷蛇生死的功能,達(dá)到了設(shè)計的目的。實驗設(shè)計效果如下圖所示:
本學(xué)期嵌入式課程在不知不覺中結(jié)束了,雖說這次課程時間不是很長,但是感覺自己收獲頗豐,不僅學(xué)習(xí)到了一些新知識,回顧了以前的一些快要遺忘的知識點,而且使自己的學(xué)習(xí)目標(biāo)更加明確,學(xué)習(xí)方法更加完善,也體會到軟件開發(fā)的趣味,更加清楚地認(rèn)識到了自己在軟件開發(fā)及學(xué)習(xí)上的一些不足之處。在這次的課程中不僅檢驗了我所學(xué)習(xí)的知識,也培養(yǎng)了我如何去把握一件事情,如何去做一件事情,又如何完成一件事情。在設(shè)計過程中,與同學(xué)分工設(shè)計,和同學(xué)們相互探討,相互學(xué)習(xí),相互監(jiān)督。學(xué)會了合作,學(xué)會了運(yùn)籌帷幄,學(xué)會了寬容,學(xué)會了理解,也學(xué)會了做人與處世。 課程是我們專業(yè)課程知識綜合應(yīng)用的實踐訓(xùn)練,著是我們邁向社會,從事職業(yè)工作前一個必不少的過程。“千里之行始于足下”,通過這次課程設(shè)計,我深深體會到這句千古名言的真正含義。也感謝老師和同學(xué)們的幫助。我今天認(rèn)真的進(jìn)行作業(yè)設(shè)計,學(xué)會腳踏實地邁開這一步,就是為以后打下堅實的基礎(chǔ)。
- /********************************************************************
- * 名 稱:int main(void)
- * 功 能:主函數(shù)
- ********************************************************************/
- #include "led.h"
- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- #include "lcd.h"
- #include "tanchishe.h"
- #include "cmlcd.h"
- #include "timeit.h"
- #include "stdlib.h"
- //畫一個大點(2*2的點)
- //x,y:坐標(biāo)
- //color:顏色
- void TP_Draw_Big_Point(u16 x,u16 y,u16 color)
- {
- POINT_COLOR=color;
- LCD_DrawPoint(x,y);//中心點
- LCD_DrawPoint(x+1,y);
- LCD_DrawPoint(x,y+1);
- LCD_DrawPoint(x+1,y+1);
- }
- int main(void)
- {
- u8 sta,sta1;
- u16 rand_color;
- delay_init(); //延時函數(shù)初始化
- uart_init(9600); //串口初始化為9600
- LED_Init(); //初始化與LED連接的硬件接口
- LCD_Init();
- time_init();
- CMLCD_Init(); // 觸摸屏初始化
- AT24CXX_Init(); //eeprom 初始化
- sta1=TP_Get_Adjdata();
- if(!sta1)
- {
- sta=CMLCD_Adjust();
- if(sta)
- {
- TP_Save_Adjdata(); //校準(zhǔn)成功就保存參數(shù)
- LCD_ShowString(40,40,100,16,16,"SUCCESSFUL!");
- }
- else
- {
- LCD_ShowString(40,40,100,16,16,"NO SUCCESSFUL!");
- }
- }
- TABCHISHE_Init();
- while(1)
- {
- delay_ms(500);
- //產(chǎn)生隨機(jī)坐標(biāo)
- if(snake.eat_sta)
- {
- snake.eat_sta=0;
- snake.rand_x=8*(1+(int)(29.0*rand()/(RAND_MAX+1.0)));
- snake.rand_y=8*(1+(int)(34.0*rand()/(RAND_MAX+1.0)));
- rand_color=LCD_ReadPoint(snake.rand_x,snake.rand_y);
- while(rand_color==BLUE) //隨機(jī)點不能是蛇身上的點
- {
- snake.rand_x=8*(1+(int)(29.0*rand()/(RAND_MAX+1.0)));
- snake.rand_y=8*(1+(int)(34.0*rand()/(RAND_MAX+1.0)));
- rand_color=LCD_ReadPoint(snake.rand_x,snake.rand_y);
- }
- LCD_Fill(snake.rand_x,snake.rand_y,snake.rand_x+snake.size,snake.rand_y+snake.size,RED);
- }
- LED0=!LED0;
- TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE ); //關(guān)中斷 防止中斷服務(wù)函數(shù)對 顯示坐標(biāo)的影響
- snake.eat_sta=show(snake.d1);
- disappear(snake.d2,turn);
- TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //開中斷
- }
- }
- /*******************************************************************
- * 名 稱:void TABCHISHE_Init(void)
- * 功 能:貪吃蛇初始化
- ********************************************************************/
- void TABCHISHE_Init(void)
- {
- Shuzu_Init(turn); // 轉(zhuǎn)向數(shù)組初始化
- LCD_Clear(WHITE);
- POINT_COLOR=RED;
- LCD_DrawLine(0,282, 240, 282);
- LCD_DrawLine(120,280, 120, 320);
- LCD_ShowString(20,290,72,12,12,"left/down");
- LCD_ShowString(20,303,36,12,12,"score:");
- LCD_ShowString(140,290,64,12,12,"right/up");
-
- // 以下為貪吃蛇程序初始化
- LCD_Fill(120,160,136,168,BLUE); //一開始蛇長度為2個SIZE
- snake.eat_sta=0;
- snake.length=2;
- LCD_ShowxNum(56,303,snake.length,3,12,0x80);
- snake.max=MAX;
- snake.size=8;
- snake.d1=0;
- snake.d2=0;
- snake.x1=128;snake.x2=snake.x1+snake.size;snake.y1=160;snake.y2=snake.y1+snake.size;
- snake.X1=112;snake.X2=snake.X1+snake.size;snake.Y1=160;snake.Y2=snake.Y1+snake.size;
- snake.rand_x=8*(1+(int)(29.0*rand()/(RAND_MAX+1.0)));
- snake.rand_y=8*(1+(int)(34.0*rand()/(RAND_MAX+1.0)));
- LCD_Fill(snake.rand_x,snake.rand_y,snake.rand_x+snake.size,snake.rand_y+snake.size,RED);
- }
- /*******************************************************************
- * 名 稱:void disappear(u8 d,u16 turn[MAX][3])
- * 功 能:貪吃蛇移動尾部消失格子
- ********************************************************************/
- //新消失的一格
- //參數(shù): 往左消失,往右消失
- void disappear(u8 d,u16 turn[MAX][3])
- {
- int i=0;
- if(d==0) //默認(rèn) 方向為從左到右
- {
- snake.X1=snake.X1+snake.size;snake.X2=snake.X2+snake.size;
- LCD_Fill(snake.X1,snake.Y1,snake.X2,snake.Y2,WHITE); //新顯示的一格
- }
- else if(d==1) //方向為下到上
- {
- snake.Y1=snake.Y1-snake.size;snake.Y2=snake.Y2-snake.size;
- LCD_Fill(snake.X1,snake.Y1,snake.X2,snake.Y2,WHITE); //新顯示的一格
- }
- else if(d==2) //方向為右到左
- {
- snake.X1=snake.X1-snake.size;snake.X2=snake.X2-snake.size;
- LCD_Fill(snake.X1,snake.Y1,snake.X2,snake.Y2,WHITE); //新顯示的一格
- }
- else if(d==3) //方向為上到下
- {
- snake.Y1=snake.Y1+snake.size;snake.Y2=snake.Y2+snake.size;
- LCD_Fill(snake.X1,snake.Y1,snake.X2,snake.Y2,WHITE); //新顯示的一格
- }
- for(i=0;i<MAX;i++) //先判斷是否是轉(zhuǎn)方向點
- {
- if(snake.X1==turn[i][0]&&snake.Y1==turn[i][1])
- {
- snake.d2=turn[i][2];
- turn[i][0]=400; //轉(zhuǎn)向完畢 清除記錄的坐標(biāo)(將坐標(biāo)變?yōu)長CD以外區(qū)域)
- turn[i][1]=400;
- break;
- }
- }
-
- }
- /*******************************************************************
- * 名 稱:u8 show(u8 d)
- * 功 能:貪吃蛇移動前部新增格子
- ********************************************************************/
-
- //新顯示的一格
- //參數(shù): 往左顯示,往右顯示
- u8 show(u8 d)
- {
- static u8 i=0;
- u16 color,color1;
- //判斷是否撞到自己的身體
- if(d==0)
- {
- color=LCD_ReadPoint(snake.x2+4,snake.y2-4);
- color1=LCD_ReadPoint(snake.x2+3,snake.y2-3);
- if(color==BLUE&&color1==BLUE)
- {
- LCD_ShowString(40,40,100,16,16,"NO SUCCESSFUL!");
- printf("color%x color1%x\r\n",color,color1);
- printf("shezhuangziji0\r\n");
- delay_ms(5000);
- TABCHISHE_Init();
- d=snake.d1;
- }
- }
- else if(d==1)
- {
- color=LCD_ReadPoint(snake.x1+4,snake.y1-4);
- color1=LCD_ReadPoint(snake.x1+3,snake.y1-3);
- if(color==BLUE&&color1==BLUE)
- {
- LCD_ShowString(40,40,100,16,16,"NO SUCCESSFUL!");
- printf("color%x color1%x\r\n",color,color1);
- printf("shezhuangziji1%d %d %d\r\n",snake.d1,snake.d2,d);
- delay_ms(5000);
- TABCHISHE_Init();
- d=snake.d1;
- printf("%d %d %d\r\n",snake.d1,snake.d2,d);
- }
- }
- else if(d==2)
- {
- color=LCD_ReadPoint(snake.x1-4,snake.y1+4);
- color1=LCD_ReadPoint(snake.x1-3,snake.y1+3);
- if(color==BLUE&&color1==BLUE)
- {
- LCD_ShowString(40,40,100,16,16,"NO SUCCESSFUL!");
- printf("color%x color1%x\r\n",color,color1);
- printf("shezhuangziji2\r\n");
- delay_ms(5000);
- TABCHISHE_Init();
- d=snake.d1;
- }
- }
- else if(d==3)
- {
- color=LCD_ReadPoint(snake.x2-4,snake.y2+4);
- color1=LCD_ReadPoint(snake.x2-3,snake.y2+3);
- if(color==BLUE&&color1==BLUE)
- {
- LCD_ShowString(40,40,100,16,16,"NO SUCCESSFUL!");
- printf("color%x color1%x\r\n",color,color1);
- printf("shezhuangziji3\r\n");
- delay_ms(5000);
- TABCHISHE_Init();
- d=snake.d1;
- }
- }
- if((snake.y1==0&&d==1)||(snake.x1==0&&d==2)||(snake.y2==280&&d==3)||(snake.x2==240&&d==0)) //蛇撞到墻了
- {
- LCD_ShowString(40,40,100,16,16,"NO SUCCESSFUL!");
- printf("shezhuangqiang\r\n");
- delay_ms(5000);
- TABCHISHE_Init();
- d=snake.d1;
- }
- if(snake.rand_x==snake.x1&&snake.rand_y==snake.y1) //判斷是否增加長度即碰到隨機(jī)點
- {
- i=1;
- if(snake.d2==0)
- {snake.X1-=16;snake.X2-=16;} //在尾端增加一格
- else if(snake.d2==1)
- {snake.Y1+=16;snake.Y2+=16;}
- else if(snake.d2==2)
- {snake.X1+=16;snake.X2+=16;}
- else if(snake.d2==3)
- {snake.Y1-=16;snake.Y2-=16;}
- snake.length++;
- LCD_ShowxNum(56,303,snake.length,3,12,0x80);
- }
- if(d==0) //默認(rèn) 方向為從左到右
- {
- snake.x1=snake.x1+snake.size;snake.x2=snake.x2+snake.size;
- LCD_Fill(snake.x1,snake.y1,snake.x2,snake.y2,BLUE); //新顯示的一格
- }
- else if(d==1) //方向為下到上
- {
- snake.y1=snake.y1-snake.size;snake.y2=snake.y2-snake.size;
- LCD_Fill(snake.x1,snake.y1,snake.x2,snake.y2,BLUE); //新顯示的一格
- }
- else if(d==2) //方向為右到左
- {
- snake.x1=snake.x1-snake.size;snake.x2=snake.x2-snake.size;
- LCD_Fill(snake.x1,snake.y1,snake.x2,snake.y2,BLUE); //新顯示的一格
- }
- else if(d==3) //方向為上到下
- {
- snake.y1=snake.y1+snake.size;snake.y2=snake.y2+snake.size;
- LCD_Fill(snake.x1,snake.y1,snake.x2,snake.y2,BLUE); //新顯示的一格
- }
- if(i==1)
- { i=0;return 1;}
- return 0;
- }
- /*******************************************************************
- * 名 稱:void CM_Scan()
- * 功 能:觸摸屏掃描函數(shù)
- ********************************************************************/
- void CM_Scan()
- {
- static u8 times=0;
- static u8 i=0;
- if(TPEN==0&&!times)
- {
- times=1;
- if(CMLCD_GetLCD()) //取坐標(biāo)成功后再選擇是否轉(zhuǎn)向
- {
- if(cmlcdxy.X>=0&&cmlcdxy.X<=120&&cmlcdxy.Y>=280&&cmlcdxy.Y<=320)
- {
- if(snake.d1==0||snake.d1==2)
- snake.d1=3;
- else if(snake.d1==1||snake.d1==3)
- snake.d1=2;
- turn[i][0]=snake.x1; //第i次轉(zhuǎn)彎坐標(biāo)
- turn[i][1]=snake.y1;
- turn[i][2]=snake.d1; //第i次轉(zhuǎn)彎方向
- i++;
- if(i>MAX-1)
- i=0;
- }
- else if(cmlcdxy.X>=121&&cmlcdxy.X<=240&&cmlcdxy.Y>=280&&cmlcdxy.Y<=320)
- {
- if(snake.d1==0||snake.d1==2)
- snake.d1=1;
- else if(snake.d1==1||snake.d1==3)
- snake.d1=0;
- turn[i][0]=snake.x1; //第i次轉(zhuǎn)彎坐標(biāo)
- turn[i][1]=snake.y1; //第i次轉(zhuǎn)彎方向
- turn[i][2]=snake.d1;
- i++;
- if(i>MAX-1)
- i=0;
- }
- }
- }else if(TPEN==1) times=0;
- }
復(fù)制代碼
完整的Word格式文檔51黑下載地址:
|