摘 要: 基于Keil for ARM集成開發(fā)環(huán)境,,設(shè)計(jì)了一種以單片機(jī)STM32F103C8T6為核心的LCD12864液晶顯示系統(tǒng),可以在屏幕任意位置實(shí)現(xiàn)字符顯示和圖形顯示,,同時(shí)實(shí)現(xiàn)了貪吃蛇游戲的功能,。該系統(tǒng)操作便捷,界面友好,,具有功耗低、速度快,、性價(jià)比高等優(yōu)點(diǎn),。
關(guān)鍵詞: STM32F103C8T6,;LCD12864;貪吃蛇游戲
0 引言
隨著社會(huì)的不斷發(fā)展,,人們對(duì)終端顯示器的要求越來越高,,體積小、重量輕,、功耗低,、清晰度高的LCD顯示器無疑成為大家心中理想的選擇[1]。與傳統(tǒng)的CRT相比,,基于單片機(jī)的LCD顯示系統(tǒng)具有硬件結(jié)構(gòu)簡(jiǎn)單,、控制方便、成本低等優(yōu)點(diǎn),,在現(xiàn)代嵌入式系統(tǒng)中已得到廣泛的運(yùn)用,。本文設(shè)計(jì)了一種基于單片機(jī)STM32F103C8T6和LCD12864的液晶顯示系統(tǒng),可以實(shí)現(xiàn)字符,、圖形的顯示,,并在此基礎(chǔ)上設(shè)計(jì)了一個(gè)貪吃蛇游戲?qū)嵗?/p>
1 系統(tǒng)硬件設(shè)計(jì)
LCD顯示系統(tǒng)主要由單片機(jī)、LCD顯示模塊,、電源模塊,、4×4矩陣鍵盤、通信接口電路組成,。系統(tǒng)方框圖如圖1所示,。
系統(tǒng)電源部分可以使用5 V電源端口供電,再通過3.3 V穩(wěn)壓芯片ASM1117-3.3得到單片機(jī)與LCD顯示模塊所需電源,。單片機(jī)采用ST公司的芯片STM32F103C8T6,,4×4矩陣鍵盤作為系統(tǒng)的輸入設(shè)備,采用LCD12864液晶顯示模塊作為系統(tǒng)的顯示部分,。單片機(jī)系統(tǒng)通過處理鍵盤輸入數(shù)據(jù)后,,根據(jù)不同的情況對(duì)顯示屏發(fā)出不同的操作指令。通信接口電路主要是由芯片PL2303構(gòu)成,,它的功能主要是將電腦的USB接口轉(zhuǎn)換為串口,,同時(shí)還將PC的邏輯電平轉(zhuǎn)換為與單片機(jī)系統(tǒng)相同的CMOS電平,方便程序的燒寫以及與上位機(jī)的通信,。
1.1 Keil MDK和單片機(jī)STM32F103C8T6簡(jiǎn)介
Keil MDK是德國(guó)Keil公司為基于Cortex-M,、ARM7、ARM9等系列處理器提供的一款集成開發(fā)環(huán)境,,支持程序的編輯,、編譯、鏈接以及在線調(diào)試等功能,,可以自動(dòng)配置啟動(dòng)代碼,,簡(jiǎn)單易學(xué),,性能優(yōu)越,能滿足大多數(shù)嵌入式應(yīng)用[2],。
STM32F103C8T6是一款基于ARM 32位的Cortext M3內(nèi)核的單片機(jī),,2.0~3.6 V的寬電壓供電范圍,CPU工作頻率最大可達(dá)72 MHz,,具有單周期的乘法指令和硬件除法,,以及優(yōu)先級(jí)可編程的中斷系統(tǒng)。同時(shí)它還具有64 KB的Flash存儲(chǔ)器與20 KB的SRAM存儲(chǔ)器,,另外還集成了非常豐富的片內(nèi)外設(shè),,如看門狗、定時(shí)器,、GPIO口,、DMA控制器、ADC,、UART,、SPI接口、IIC接口等,,具有成本低,、速度快、性價(jià)比高等優(yōu)點(diǎn),。
1.2 液晶LCD12864顯示模塊
LCD12864液晶屏的數(shù)據(jù)接口是串行的,,工作電壓為2.8~5.5 V,像素為128×64,,顯示顏色為黑白色,,背光顏色為藍(lán)色,不帶字庫(kù),。模塊內(nèi)部采用的控制器為ST7565P,,功耗非常低,在省電模式下的工作電流最大僅為5 A,,顯示模塊僅有8個(gè)引腳接口,,占用主控制器的I/O數(shù)量少。LCD12864引腳說明如表1所示,。
1.3 LCD12864與單片機(jī)STM32F103C8T6的硬件連接
單片機(jī)STM32F103C8T6與LCD顯示模塊的硬件連接非常簡(jiǎn)單,,如圖2所示。LCD12864引腳編號(hào)為1~5的控制端口可以直接與STM32F103C8T6單片機(jī)的GPIO口相連,,第8引腳是LCD的背光電源端口,,通過單片機(jī)的一個(gè)I/O口控制三極管的導(dǎo)通來控制背光電源的通斷,從而節(jié)省功耗[3]。
2 系統(tǒng)軟件設(shè)計(jì)
系統(tǒng)軟件設(shè)計(jì)主要包括LCD初始化,、寫數(shù)據(jù),、寫命令,以及畫點(diǎn),、字符顯示等程序設(shè)計(jì)。液晶顯示模塊正常工作前,,需要對(duì)其進(jìn)行初始化,,主要包括復(fù)位液晶、確定顯示對(duì)比度,、偏壓比等參數(shù),,然后才能實(shí)現(xiàn)字符、圖形以及其他的顯示功能,。在向液晶顯示模塊寫入數(shù)據(jù)或者命令時(shí),,一定要注意寫入的時(shí)序,只有嚴(yán)格地按照時(shí)序編寫驅(qū)動(dòng)程序才能正常工作,。設(shè)計(jì)程序時(shí),,為了方便移植,可以將相關(guān)引腳的操作用宏封裝起來,,如將片選引腳拉低的操作可以用宏LCD_CS_0()定義[4-5],。寫數(shù)據(jù)命令的功能函數(shù)如下:
void LCD12864_WriteCommand(uint8 Cmd)
{……
LCD_CS_0();//打開片選
LCD_A0_0(),;//選擇寫命令
LCD_SCLK_0(),;//時(shí)鐘線置低
for(i=0;i<8,;i++){
if(Cmd &0x80)//如果輸出為1
LCD_SI_1(),;//SI數(shù)據(jù)線輸出為1
else
LCD_SI_0();//SI數(shù)據(jù)線輸出為0
LCD_SCLK_1(),;//寫入數(shù)據(jù)
Dat<<=1,;
LCD_SCLK_0();//置低SCLK時(shí)鐘線
} LCD_CS_1(),;//關(guān)閉片選
}
寫數(shù)據(jù)功能函數(shù)void LCD12864_WriteData(uint8 Dat)實(shí)現(xiàn)方法與寫命令功能函數(shù)相同,,只是打開片選后,選擇的是寫數(shù)據(jù)LCD_A0_1(),。
在設(shè)計(jì)LCD液晶驅(qū)動(dòng)程序時(shí),,最基本的功能就是在屏幕的任意位置顯示一個(gè)點(diǎn),然后在此基礎(chǔ)上實(shí)現(xiàn)更復(fù)雜的功能,。但是每次寫入的數(shù)據(jù)都包含了8個(gè)點(diǎn)的信息,,而且該LCD顯示模塊沒有讀控制端口,不能通過讀數(shù)據(jù)的命令了解其他7個(gè)點(diǎn)的狀態(tài),這樣就不能達(dá)到最終的目的,。為了解決這個(gè)問題,,可以在單片機(jī)的內(nèi)存區(qū)開辟一個(gè)數(shù)據(jù)空間,來記錄顯示器上每個(gè)點(diǎn)的顯示情況,,代碼如下:
static uint8 LCD_RAM[128*8]={0},;//開辟顯示緩沖區(qū)
void LCD12864_DrawPoint(uint8 x,uint8 y,,uint8 Point_Flag)
{
if(Point_Flag==0)
{LCD_RAM[x+128*(7-(y>>3))]&=(~(1<<(7-(y&0x07)))),;}
if(Point_Flag==1)
{LCD_RAM[x+128*(7-(y>>3))]|=(1<<(7-(y&0x07)));}LCD12864_WriteCommand(0xB0+(7-((y>>3)&0x0F))),;//寫頁地址
LCD12864_WriteCommand(0x10+((x>>4)&0x0F)),;
//寫列地址,高低字節(jié)兩次寫入
LCD12864_WriteCommand(0x00+(x&0x0F)),;
LCD12864_WriteData(LCD_RAM[x+128*(7-(y>>3))]),;
//寫入數(shù)據(jù)
}
因?yàn)橐壕K未帶字庫(kù),在字符顯示前,,需要將其字模存入單片機(jī)的程序存儲(chǔ)空間中,,然后在任意坐標(biāo)顯示一個(gè)點(diǎn)的基礎(chǔ)上,實(shí)現(xiàn)字符的顯示,。8×16字符顯示的驅(qū)動(dòng)程序如下:
void LCD12864_PutChar8x16(uint32 Char_x,,uint32 Char_y,uint8 c)
{……
Temp=Font8x16[c*16+i],;//獲取字模
for(j=0,;j<8;j++)
{if(Temp&0x80)
{LCD12864_DrawPoint(Char_x+j,,Char_y-i,,1);}
else{LCD12864_DrawPoint(Char_x+j,,Char_y-i,,0);}
Temp<<=1,;}}}
3 實(shí)例設(shè)計(jì)
以單片機(jī)STM32F103C8T6作為控制核心,,在LCD12864驅(qū)動(dòng)程序的基礎(chǔ)上,實(shí)現(xiàn)了貪吃蛇游戲的功能,。貪吃蛇游戲程序主要分為3個(gè)子程序模塊,,即鍵盤掃描模塊、LCD12864驅(qū)動(dòng)模塊和貪吃蛇游戲數(shù)據(jù)處理模塊,。貪吃蛇程序流程圖如圖3所示,。
游戲中的食物和蛇可以看作兩個(gè)不同的對(duì)象,,它們的屬性可以用兩個(gè)結(jié)構(gòu)體變量來描述,然后根據(jù)游戲功能將整個(gè)大模塊合理地劃分為各個(gè)子模塊,,并編寫相應(yīng)的功能函數(shù),,供主模塊函數(shù)調(diào)用。在設(shè)計(jì)程序時(shí),,定義蛇的最長(zhǎng)長(zhǎng)度為15,,蛇運(yùn)動(dòng)區(qū)域的長(zhǎng)為20個(gè)單位,寬為15個(gè)單位,,即橫坐標(biāo)的坐標(biāo)范圍為1~20,,縱坐標(biāo)的坐標(biāo)范圍為1~15。貪吃蛇游戲中定義了食物結(jié)構(gòu)體和蛇結(jié)構(gòu)體變量,。食物結(jié)構(gòu)體定義為:
struct{uint8 X;uint8 Y,;}Food,;
蛇體的最大長(zhǎng)度宏定義為:
#define SNAKE_LONG_MAX 15
蛇結(jié)構(gòu)體變量中定義了蛇體長(zhǎng)度、蛇的等級(jí)和蛇的分?jǐn)?shù),,具體定義為:
struct{
uint8 X[SNAKE_LONG_MAX_],;
uint8 Y[SNAKE_LONG_MAX];
uint8 Long,;
uint8 Level,;
uint16 Score;}Snake,;
顯示無符號(hào)整形數(shù)據(jù)功能函數(shù)定義為:
void LCD12864_PutUintNumber(uint32 Num_x,,uint32Num_y,uint32 Uint_Num,,uint8 Num_N)
顯示或者熄滅一個(gè)蛇體單位功能函數(shù)定義為:
void DiaplaySnakePoint(uint8 x,,uint8 y,uint8 Point_Stu)
判斷蛇是否死亡的程序如下:
if((Snake.X[0]<1)||(Snake.X[0]>20)||(Snake.Y[0]<1)||(Snake.Y[0]>15))
{Game_Fail(),;}
for(i=4,;i<Snake.Long;i++){if((Snake.X[0]==Snake.X[i])&&(Snake.Y[0]==Snake.Y[i])){Game_Fail(),;}}
判斷蛇是否吃到食物程序如下:
if((Snake.X[0]==Food.X)&&(Snake.Y[0]==Food.Y))
{Snake.Long++,;//蛇身長(zhǎng)度加1
Snake.Score+=10;//得分?jǐn)?shù)增加
LCD12864_PutUintNumber(96,,63-48,,Snake.Score,4),;
//屏幕上更新分?jǐn)?shù)
Snake.X[Snake.Long-1]=Snake_End_x,;
Snake.Y[Snake.Long-1]=Snake_End_y;
DiaplaySnakePoint(Snake_End_x,Snake_End_y,,1),;
//蛇體向后增長(zhǎng)1個(gè)單位
Put_Food();//放置食物
}Delayms(3000-300*Snake.Level),;//根據(jù)蛇體等級(jí)延時(shí)
在貪吃蛇游戲的程序設(shè)計(jì)中,,放置食物的程序會(huì)涉及如何獲取隨機(jī)數(shù)的問題,為了增加游戲的隨機(jī)性,,本次設(shè)計(jì)不采用偽隨機(jī)數(shù)產(chǎn)生的方法,,而是利用單片機(jī)的AD采樣引腳在懸空的情況下采樣,獲得的AD值作為隨機(jī)種子,,然后通過一系列的運(yùn)算來得到隨機(jī)數(shù),,經(jīng)過實(shí)踐得知,此種方式得到的隨機(jī)數(shù)更真實(shí),,效果很好,。食物放置程序如下:
void Put_Food(void){…..
AD_Temp=ADC_ConvertedValue;//獲取隨機(jī)種子
Food.X=(AD_Temp%20)+1,;
//隨機(jī)獲取食物橫坐標(biāo)(1~20)
Food.Y=(AD_Temp%15)+1,;
//隨機(jī)獲取食物縱坐標(biāo)(1~15)
……
DiaplaySnakePoint(Food.X,F(xiàn)ood.Y,,1),;//顯示食物
}
4 結(jié)論
STM32F103C8T6是一款高性能的單片機(jī),LCD12864硬件接口簡(jiǎn)單,,所占用單片機(jī)的I/O口資源非常少,,單片機(jī)有足夠的硬件資源供其他外設(shè)使用,顯示系統(tǒng)可以作為其他嵌入式系統(tǒng)的一部分,,運(yùn)用于不同的顯示場(chǎng)合,;系統(tǒng)的程序設(shè)計(jì)采用的是C語言,其移植性非常好,,模塊化的設(shè)計(jì)思想可以在系統(tǒng)中靈活地?cái)U(kuò)展其他功能,,滿足不同的顯示要求。
參考文獻(xiàn)
[1] 劉金星,,李洪文.基于高速單片機(jī)的液晶顯示模塊控制[J].液晶與顯示,,2011,26(1):88-91.
[2] 韓敬海,,王蕊.Cortext-M3開發(fā)技術(shù)與實(shí)現(xiàn)[M].西安:西安電子科技大學(xué)出版社,,2013.
[3] 陳楊楊,陳梅.基于PIC18F458單片機(jī)的LCD顯示[J].儀表技術(shù),,2005(4):52-53.
[4] 武俊鵬,,張國(guó)印,,姚愛紅,等.基于ARM的嵌入式系統(tǒng)設(shè)計(jì)實(shí)驗(yàn)與實(shí)踐教程[M].北京:清華大學(xué)出版社,,2011.
[5] 石紅曉,,吳光敏.基于Nios II處理器的TFT-LCD圖形顯示設(shè)計(jì)[J].微型機(jī)與應(yīng)用,2010,,29(18):37-39.