一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)_第1頁
一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)_第2頁
一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)_第3頁
一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)_第4頁
一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)_第5頁
已閱讀5頁,還剩40頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、QQ 64134703一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) 12在各類儀器儀表的設(shè)計(jì)中,常常需要透過液晶和鍵盤來實(shí)現(xiàn)人機(jī)交互,當(dāng)整個(gè)系統(tǒng)需要管理的內(nèi)容較多的時(shí)候,如何透過鍵盤和液晶實(shí)現(xiàn)有效管理便是個(gè)問題。通常軟件的設(shè)計(jì)者會(huì)設(shè)計(jì)一個(gè)菜單界面來達(dá)到這個(gè)目的。本代碼便是透過對(duì)身邊常見的手機(jī)的界面做分析,總結(jié),然后通過C代碼實(shí)現(xiàn)類似的界面。這套代碼實(shí)現(xiàn)的菜單的特點(diǎn):1 支持3種菜單類型2 支持多國(guó)語言3 占用內(nèi)存極小4 全C代碼,方便移植5 支持?jǐn)?shù)字按鍵快捷方式一些手機(jī)界面的分析常見的手機(jī)界面幾乎都可以歸類為這3種:圖標(biāo)層,條項(xiàng)層,動(dòng)態(tài)內(nèi)容層* 圖標(biāo)層圖標(biāo)層基本特征是:使

2、用圖標(biāo)和標(biāo)題配合圖1 圖標(biāo)層菜單圖標(biāo)層通常作為菜單系統(tǒng)的頂層,標(biāo)題文字可以根據(jù)語言選擇而更改,但圖標(biāo)通常不變。而且右邊有滾動(dòng)條提示當(dāng)前位置。底部的一個(gè)詞作為按鍵的功能提示。也見過把滾動(dòng)條橫向放置在屏幕底部的,除了通過滾動(dòng)條顯示當(dāng)前位置外,也有可能通過編號(hào)來提示當(dāng)前位置。2 作者:梁炎昌 Email: 最后更新:2007-9-1QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)功能提示提示不是必須的,而且功能提示只有在按鍵安放在液晶附近才能使用,否則操作者根本不知道這個(gè)功能提示對(duì)應(yīng)于那個(gè)按鍵。如果硬件設(shè)計(jì)時(shí),功能提示的優(yōu)點(diǎn)是顯示了對(duì)應(yīng)位置按鍵的實(shí)際功能,方便操作者。在圖1中,”Phone

3、book”電話簿”是標(biāo)題,”Select”進(jìn)入”是按鍵的功能提示。 在大部分的手機(jī)中,圖標(biāo)不單單是靜態(tài)的,通常在上下翻的時(shí)候,先是圖標(biāo)動(dòng)畫,然后才變成靜態(tài)圖標(biāo)。圖2 圖標(biāo)層菜單在圖2的左圖中除了中間的大圖標(biāo)外,還有右邊的一欄小圖標(biāo),類似滾動(dòng)條的作用,底部有3個(gè)按鍵的功能提示。而圖2的右圖中僅按鍵的功能提示有兩個(gè),圖標(biāo)在屏幕的左邊。當(dāng)然了,形式可以多變,但本質(zhì)依然是:圖標(biāo)標(biāo)題。* 條項(xiàng)層條項(xiàng)層的基本特征是:一行行的文字圖3 條項(xiàng)層菜單QQ 64134703項(xiàng)是當(dāng)前選中的菜單項(xiàng)。 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) 條項(xiàng)層菜單通過顯示一行行的文字作為菜單選擇項(xiàng)。通過反顯/高亮某行文字來提示該右邊依然

4、可能有滾動(dòng)條,提示選中的菜單項(xiàng)在整個(gè)菜單中位置。也依然可能有數(shù)字編號(hào)提示選中的菜單項(xiàng)在整個(gè)菜單中的位置。使用滾動(dòng)條和數(shù)字編號(hào)的目的在于提示菜單項(xiàng)位置,但滾動(dòng)條和數(shù)字編號(hào)均不是必須的。尤其在屏幕較小時(shí),或者實(shí)現(xiàn)滾動(dòng)條較復(fù)雜時(shí),通常省略。也依然有可能使用按鍵的功能提示,但也不是必須的。 在黑白液晶中,通常用反顯整行文字來提示,但有時(shí)比較耗費(fèi)CPU,那么可以在需要提示的菜單項(xiàng)前顯示個(gè)箭頭,以箭頭來提示選中的菜單項(xiàng)。移動(dòng)一個(gè)箭頭的位置,比取消反顯行并反顯新一行的代價(jià)會(huì)小很多,在CPU主頻不高時(shí)可以使用。圖4 條項(xiàng)層菜單在彩色屏幕中,高亮顯示選中的選擇項(xiàng),方法很多,可以通過改動(dòng)背景顏色和文字顏色等方法實(shí)

5、現(xiàn)。反顯/高亮,或者使用箭頭,目的是要突出選中的菜單項(xiàng)。* 動(dòng)態(tài)內(nèi)容層動(dòng)態(tài)內(nèi)容層由標(biāo)題和動(dòng)態(tài)內(nèi)容組成。標(biāo)題用來說明當(dāng)前項(xiàng)的功能,而動(dòng)態(tài)內(nèi)容就是該功能當(dāng)前狀態(tài)。比如“設(shè)置時(shí)間”,動(dòng)態(tài)內(nèi)容就顯示當(dāng)前的時(shí)間。標(biāo)題是固定的,根據(jù)語言切換的,而動(dòng)態(tài)內(nèi)容可能需要調(diào)用一個(gè)函數(shù)得到,然后顯示。 動(dòng)態(tài)內(nèi)容通常是一些設(shè)置內(nèi)容的開關(guān)狀態(tài)等。依然有可能有滾動(dòng)條和數(shù)字編號(hào),以及按鍵的功能提示。動(dòng)態(tài)內(nèi)容層菜單一樣可以顯示多個(gè)項(xiàng),這點(diǎn)跟條項(xiàng)層菜單一樣。當(dāng)屏幕可以顯示多個(gè) 3QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)項(xiàng)時(shí),那么依然需要使用跟條項(xiàng)層菜單的方法來提示當(dāng)前選中的菜單項(xiàng)。而當(dāng)由于屏幕較小時(shí),僅能顯示一個(gè)

6、動(dòng)態(tài)內(nèi)容項(xiàng)菜單,那么不需要提示選中,因?yàn)槠聊灰簿鸵粋€(gè)項(xiàng)。圖5中僅有一項(xiàng)菜單,無須通過反顯提示當(dāng)前菜單項(xiàng)。圖6中有3個(gè)菜單項(xiàng),要通過高亮的方式提示當(dāng)前選中的菜單項(xiàng)。圖5 僅有一項(xiàng)菜單的動(dòng)態(tài)內(nèi)容層菜單圖6 有多項(xiàng)的動(dòng)態(tài)內(nèi)容層菜單在條項(xiàng)層和動(dòng)態(tài)內(nèi)容層也有可能會(huì)有本層菜單的標(biāo)題,只要屏幕足夠大。在條項(xiàng)層和動(dòng)態(tài)內(nèi)容層菜單中,按鍵的功能提示可能會(huì)依據(jù)當(dāng)前選中的菜單項(xiàng)而改變。 圖7中由于屏幕夠大,顯示本層菜單標(biāo)題。QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)圖7帶標(biāo)題的菜單圖標(biāo)層代碼實(shí)現(xiàn)分析上下翻轉(zhuǎn)是需要刷新圖標(biāo)和標(biāo)題,偶爾也需要更改底部的按鍵功能提示。因此實(shí)現(xiàn)方法也就很簡(jiǎn)單了,根據(jù)上下翻轉(zhuǎn)鍵刷

7、新文字和圖標(biāo)。滾動(dòng)條通過當(dāng)前位置和總的菜單項(xiàng)可以實(shí)現(xiàn)。條項(xiàng)層代碼實(shí)現(xiàn)分析 分兩種情況:1 要求顯示的全部菜單項(xiàng)多于LCD可以顯示的菜單項(xiàng)的數(shù)目。比如,要求顯示的項(xiàng)有6項(xiàng),但是LCD一次僅僅能顯示3項(xiàng),那么就涉及到如何刷新顯示的問題了。對(duì)照?qǐng)D8,可分成如下3類情況:A頂部上移,當(dāng)前反顯項(xiàng)在LCD頂部,上翻。那么就是刷新整個(gè)3項(xiàng)的顯示了,因?yàn)?項(xiàng)的內(nèi)容都更改了。B底部下移,當(dāng)前反顯項(xiàng)在LCD底部,下翻。那么就是刷新整個(gè)3項(xiàng)的顯示了,因?yàn)?項(xiàng)的內(nèi)容都更改了。C除了AB兩種之外的都是當(dāng)前反顯項(xiàng)在LCD內(nèi)部移動(dòng),取消原來的反顯項(xiàng),根據(jù)上下翻來反顯當(dāng)前項(xiàng)。QQ 64134703一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的

8、實(shí)現(xiàn) 圖8 條項(xiàng)層菜單上下翻的分析圖中Item表示當(dāng)前顯示項(xiàng)的編號(hào),Where表示當(dāng)前顯示項(xiàng)在液晶上的位置。可見上圖中Item的取值范圍是04,where的取值范圍是02。2 要求顯示的項(xiàng)不多于LCD可以顯示的項(xiàng)的數(shù)目。對(duì)照?qǐng)D9,有3種情況:A頂部上移,取消頂部反顯,反顯底部。B底部下移,取消底部反顯,反顯頂部。C除了AB兩種之外的都是當(dāng)前反顯項(xiàng)在LCD內(nèi)部移動(dòng),取消原來的反顯項(xiàng),根據(jù)上下翻來反顯當(dāng)前項(xiàng)。QQ 64134703一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) 圖9 條項(xiàng)層菜單上下翻的分析 從硬件行為上來分析,在某一層的菜單中,可以有:上翻,下翻,確定,退出這4種情況,上翻和下翻是在本層菜單內(nèi)瀏

9、覽菜單項(xiàng),確定是進(jìn)入選中菜單項(xiàng)的子菜單,退出是退出當(dāng)前菜單,回到上層菜單。對(duì)于條項(xiàng)層菜單,每一層條項(xiàng)型菜單用5個(gè)函數(shù)來實(shí)現(xiàn),分別是:表格1 條項(xiàng)菜單函數(shù) MenuNameInitMenuNameUpMenuNameDownMenuNameLeftMenuNameRight 初始化本層菜單 向上按鍵處理函數(shù),向上按鍵默認(rèn)作為確定鍵,用來進(jìn)入子菜單或確定輸入。 向下按鍵處理函數(shù),向下按鍵默認(rèn)作為退出鍵,用來返回父菜單或取消輸入。 向左按鍵處理函數(shù),選中上一項(xiàng)菜單項(xiàng) 向右按鍵處理函數(shù),選中下一項(xiàng)菜單項(xiàng)* MenuName是菜單名,層菜單均有一個(gè)菜單名。當(dāng)有按鍵輸入時(shí),這些函數(shù)會(huì)被調(diào)用,代碼中設(shè)計(jì)了一

10、個(gè)FSM來管理多層菜單,每一層菜單在FSM的一個(gè)索引表格中占用5個(gè)索引號(hào),分別對(duì)應(yīng)于表格1的5個(gè)函數(shù)。代碼運(yùn)行時(shí),保存著當(dāng)前的索引號(hào),當(dāng)按鍵按下的時(shí)候,代碼會(huì)在這個(gè)索引表格中找到下一個(gè)索引號(hào),以此作為當(dāng)前索引號(hào),同時(shí)會(huì)調(diào)用這個(gè)索引號(hào)對(duì)應(yīng)的條項(xiàng)菜單函數(shù)。表格2 索引表中函數(shù)和索引號(hào)的對(duì)應(yīng)關(guān)系函數(shù)MenuNameInitMenuNameUpMenuNameDownMenuNameLeftMenuNameRight索引號(hào) MenuNameInit_ID MenuNameInit_ID+1 MenuNameInit_ID+2 MenuNameInit_ID+3 MenuNameInit_ID+4 當(dāng)當(dāng)

11、前狀態(tài)為表格中的MenuNameInit_ID+1至 MenuNameInit_ID+4時(shí),是臨時(shí)狀態(tài),所謂“臨時(shí)狀態(tài)”是指與這4個(gè)索引號(hào)對(duì)應(yīng)函數(shù)在被調(diào)用的時(shí)候,依然會(huì)修改當(dāng)前索引,MenuNameLeft和MenuNameRight會(huì)把索引號(hào)修改為本層菜單的MenuNameInit_ID,而MenuNameUp則會(huì)修改成某個(gè)子菜單對(duì)應(yīng)MenuNameInit_ID,MenuNameDown怎會(huì)修改成父菜單的MenuNameInit_ID。唯有MenuNameInit_ID是個(gè)恒久的狀態(tài)。QQ 64134703第一次顯示。 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) 從上層菜單進(jìn)入本層菜單后,索引號(hào)首先

12、變?yōu)楸静藛蔚腗enuNameInit_ID,同時(shí)會(huì)調(diào)用MenuNameInit函數(shù),該函數(shù)首先把一些指針修改到本層菜單的資源中,包括條項(xiàng)的文字字符串開始位置,每個(gè)字符串長(zhǎng)度,本層菜單條項(xiàng)的數(shù)目等,然后初始化本層菜單的當(dāng)向左按鍵被按下,根據(jù)當(dāng)前索引號(hào)MenuNameInit_ID索引表格中查找,查處該按鍵對(duì)應(yīng)的索引號(hào)是MenuNameInit_ID+3,于是索引號(hào)被修改為MenuNameInit_ID+3,同時(shí)調(diào)用MenuNameLeft函數(shù),MenuNameLeft函數(shù)首先維護(hù)條項(xiàng)的顯示:把上一個(gè)菜單項(xiàng)作為選中項(xiàng),代碼處理的方法是圖8圖9的方式。在MenuNameLeft函數(shù)的最后,把索引號(hào)修

13、改成MenuNameInit_ID。向右按鍵的處理跟向左按鍵的處理基本一致。當(dāng)向上按鍵被按下,根據(jù)當(dāng)前索引號(hào)MenuNameInit_ID索引表格中查找,查處該按鍵對(duì)應(yīng)的索引號(hào)是MenuNameInit_ID+1,于是索引號(hào)被修改為MenuNameInit_ID+1,同時(shí)調(diào)用MenuNameUp函數(shù),MenuNameUp函數(shù)首先調(diào)用PUSH函數(shù)把本層菜單的特征參數(shù)保存到一個(gè)模擬堆棧中,目的是為了當(dāng)從子菜單返回本層菜單時(shí),可以把模擬堆棧中保存的特征參數(shù)恢復(fù)屏幕顯示。MenuNameUp然后根據(jù)當(dāng)前選中菜單項(xiàng),修改索引號(hào)為該子菜單對(duì)應(yīng)的索引號(hào),并把一個(gè)刷新標(biāo)志Flash設(shè)置為1,在下一次鍵盤掃描中

14、,雖然沒有按鍵按下,但依然會(huì)因?yàn)镕lash為1,而調(diào)用該子菜單的MenuNameInit函數(shù),該函數(shù)初始化本層菜單的顯示。對(duì)于一個(gè)常見的條項(xiàng)型菜單,其實(shí)大部分情況每個(gè)條項(xiàng)顯示內(nèi)容在編寫程序的時(shí)候是因此條項(xiàng)型菜單某個(gè)時(shí)刻的狀態(tài)能跟如下這幾個(gè)參數(shù)有關(guān)。 已經(jīng)知道的,因此這些顯示內(nèi)容可以放在程序代碼段中,并可以通過指針尋址。 DispItem 指向顯示內(nèi)容數(shù)組開始位置的指針I(yè)tem 當(dāng)前顯示條項(xiàng)在顯示內(nèi)容數(shù)組中的偏置Where 當(dāng)前顯示條項(xiàng)在液晶上的位置恢復(fù)一個(gè)菜單原有顯示,在得到上面3個(gè)參數(shù)后,便能在屏幕重畫出菜單來。所以,在進(jìn)入子菜單前,為了能從子菜單返回時(shí),恢復(fù)本菜單顯示,需要對(duì)上3個(gè)參數(shù)做備

15、份,而這就是PUSH函數(shù)的內(nèi)容。在某個(gè)條項(xiàng)型菜單中,向下按鍵被按下,MenuNameDown函數(shù)被調(diào)用,該函數(shù)調(diào)用Pop函數(shù),Pop函數(shù)從模擬堆棧中恢復(fù)DispItem、Item、Where這3個(gè)參數(shù),并把刷新標(biāo)志ReFlash設(shè)置為1,在下一次鍵盤掃描中,雖然沒有按鍵按下,但依然會(huì)因?yàn)镽eFlash為1,而調(diào)用該子菜單的MenuNameInit函數(shù),該函數(shù)根據(jù)恢復(fù)的3個(gè)參數(shù)顯示本層菜單。MenuTop.C中有三個(gè)公共函數(shù)與之相關(guān):void BarMenuInit() 實(shí)現(xiàn)從父菜單進(jìn)入本層菜單時(shí)的初始化和從子菜單退回到本層菜單的初始化 void BarMenuLeft() 維護(hù)按下向左按鍵時(shí)的

16、條項(xiàng)顯示void BarMenuRight()維護(hù)按下向右按鍵時(shí)的條項(xiàng)顯示BarMenuInit在兩個(gè)地方被調(diào)用:剛剛從父菜單進(jìn)入到本層菜單時(shí)、從子菜單返回到 8QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)本層時(shí)。剛剛從父菜單進(jìn)入本層時(shí),Item=0 Where=0 ,代碼比較容易寫;而從子菜單返回時(shí),那么Where就跟上次進(jìn)入這個(gè)子菜單時(shí)的情形有關(guān)系了(因?yàn)榭梢苑瓌?dòng),因此Item項(xiàng)顯示在液晶上的位置是可以改變的),既然where不太確定,那么我們也只有推算出where=0地方的Item值了,然后才開始顯示,總之是需要處理Item的循環(huán)顯示。BarMenuLeft和BarMenuR

17、ight依照上面的圖和分析也是可以實(shí)現(xiàn)的。菜單框架的代碼實(shí)現(xiàn)以下內(nèi)容將分析本框架代碼中的有限狀態(tài)機(jī)的周轉(zhuǎn)機(jī)理、圖標(biāo)層的實(shí)現(xiàn)、條項(xiàng)層的實(shí)現(xiàn)。 MenuFSM.C中有一個(gè)菜單狀態(tài)的數(shù)據(jù)結(jié)構(gòu)。 定義了當(dāng)前狀態(tài)索引號(hào)、4個(gè)按鍵狀態(tài)索引號(hào)、執(zhí)行函數(shù)。void (*KeyFuncPtr)(); /按鍵功能指針typedef structU8 KeyStateIndex; /當(dāng)前狀態(tài)索引號(hào)U8 KeyUpState; /按下"向上"鍵時(shí)轉(zhuǎn)向的狀態(tài)索引號(hào)U8 KeyDnState; /按下"向下"鍵時(shí)轉(zhuǎn)向的狀態(tài)索引號(hào)U8 KeyLState; /按下"向左&q

18、uot;鍵時(shí)轉(zhuǎn)向的狀態(tài)索引號(hào)U8 KeyRState; /按下"向右"鍵時(shí)轉(zhuǎn)向的狀態(tài)索引號(hào)void (*CurrentOperate)(); /當(dāng)前狀態(tài)應(yīng)該執(zhí)行的功能操作 KbdTabStruct;把這個(gè)數(shù)據(jù)結(jié)構(gòu)例化成一個(gè)數(shù)組,我們看看這個(gè)數(shù)組中一些關(guān)鍵的代碼:_CONST_ KbdTabStruct KeyTab=/ |-> Index/ | Up/ | | Down/ | | | Left/ | | | | Right ->功能函數(shù)/ | | | | | | 0, 1, 2, 3, 4,(*DispMenuTop),/ 待機(jī)畫面 1, 0, 0, 0, 0,

19、(*DispMenuTopUp), 2, 1, 1, 1, 0,(*DispMenuTopDown), 3, 1, 1, 1, 0,(*DispMenuTopLeft), 4, 1, 1, 1, 0,(*DispMenuTopRight), 5, 6, 7, 8, 9,(*DispIcoMenuInit), /圖標(biāo)層菜單 6, 0, 0, 0, 0,(*DispIcoMenuUp), / 7, 0, 0, 0, 0,(*DispIcoMenuDown), / 8, 0, 0, 0, 0,(*DispIcoMenuLeft), / 9, 0, 0, 0, 0,(*DispIcoMenuRight

20、),/10,11,12,13,14,(*DispMenuFuncInit), /"功能"11, 0, 0, 0, 0,(*DispMenuFuncUp), /12, 0, 0, 0, 0,(*DispMenuFuncDown), /13, 0, 0, 0, 0,(*DispMenuFuncLeft), /14, 0, 0, 0, 0,(*DispMenuFuncRight),/;QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)上面的代碼是給出了:待機(jī)界面、圖標(biāo)層菜單、條項(xiàng)層菜單“功能”,實(shí)際界面如下圖:以以上的代碼段和圖片,開始實(shí)際的分析:有4個(gè)按鍵作為菜單周轉(zhuǎn)按鍵

21、:向上鍵、向下鍵、向左鍵、向右鍵。在檢查按鍵輸入時(shí)根據(jù)按鍵輸入查找出下一個(gè)狀態(tài)號(hào)和以及這個(gè)狀態(tài)號(hào)的執(zhí)行函數(shù)。Main程序在一系列初始化后,一致在執(zhí)行CheckKey函數(shù),該函數(shù)不斷檢查按鍵輸入,有按鍵輸入則根據(jù)按鍵分發(fā)處理,在退出該函數(shù)前檢查兩個(gè)全局變量ReFlash、Flash,這兩個(gè)全局變量定義在Menu.C中,在Menu.H中有聲明。U8 ReFlash = 0; /子項(xiàng)菜單返回 刷新標(biāo)志U8 Flash = 0; /跳轉(zhuǎn)進(jìn)入子菜單 刷新標(biāo)志分別作為子菜單返回時(shí),請(qǐng)求刷新的標(biāo)志和進(jìn)出子菜單時(shí),請(qǐng)求刷新的標(biāo)志,一旦這兩個(gè)標(biāo)志均不為0,那么MenuFSM.C中的CheckKey函數(shù)根據(jù)當(dāng)前索

22、引號(hào)查詢到執(zhí)行函數(shù)并執(zhí)行之,然后清除這兩個(gè)標(biāo)志。if(Flash|ReFlash)KeyFuncPtr=KeyTabKeyFuncIndex.CurrentOperate;(*KeyFuncPtr)();/執(zhí)行當(dāng)前按鍵的操作Flash = 0;ReFlash = 0;在待機(jī)界面下,當(dāng)前狀態(tài)索引號(hào)是KeyFuncIndex = 0,CheckKey函數(shù)檢查到當(dāng)按鍵輸入是向上鍵(Up)時(shí),在狀態(tài)表中查出向上按鍵的狀態(tài)號(hào)是1,更新了當(dāng)前狀態(tài)索引號(hào),然后找出狀態(tài)號(hào)1的執(zhí)行函數(shù)是DispMenuTopUp(),于是執(zhí)行這個(gè)函數(shù),然后返回,繼續(xù)檢查按鍵,繼續(xù)根據(jù)按鍵輸入實(shí)行狀態(tài)周轉(zhuǎn)。/MenuFSM.C

23、CheckKey()函數(shù)代碼片段QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)switch(KeyScan()case Key_Up: /向上鍵,找出新的菜單狀態(tài)編號(hào)KeyFuncIndex=KeyTabKeyFuncIndex.KeyUpState;KeyFuncPtr=KeyTabKeyFuncIndex.CurrentOperate;(*KeyFuncPtr)();/執(zhí)行當(dāng)前按鍵的操作break;/-case Key_Right: /向右鍵,找出新的菜單狀態(tài)編號(hào)KeyFuncIndex=KeyTabKeyFuncIndex.KeyRState;KeyFuncPtr=KeyTab

24、KeyFuncIndex.CurrentOperate;(*KeyFuncPtr)();/執(zhí)行當(dāng)前按鍵的操作break;default: /按鍵錯(cuò)誤的處理IsKey = 0;break;/兩個(gè)當(dāng)中有任意一個(gè)不為零,那么執(zhí)行一次,我們應(yīng)該不會(huì)出現(xiàn)Flash和ReFlash都是1的情況if(Flash|ReFlash)KeyFuncPtr=KeyTabKeyFuncIndex.CurrentOperate;(*KeyFuncPtr)();/執(zhí)行當(dāng)前按鍵的操作Flash = 0;ReFlash = 0;return IsKey;上面描述到程序會(huì)執(zhí)行DispMenuTopUp()函數(shù),那么我看看這個(gè)函

25、數(shù)里到底做了什么事情。 /待機(jī)界面下Up鍵的處理void DispMenuTopUp(void)/-KeyPressCount = 0;/-GUI_Clear();/-/這里是頂層菜單,因此在進(jìn)入子菜單前需要初始化變量InitMenuVal();/-/狀態(tài)跳轉(zhuǎn),進(jìn)入子菜單/jump to Menu indexJump2Menu(MenuIndex,FlashMode_AutoInit);return;該函數(shù)清屏后調(diào)用了InitMenuVal函數(shù),然后由Jump2Menu修改當(dāng)前狀態(tài)索引號(hào)為MenuIndex,MenuIndex是宏定義,值是5,置Flash為1,最后返回。InitMenuVal

26、()函數(shù)初始化了一些全局變量,然后備份了待機(jī)界面的狀態(tài)索引號(hào)。/初始化全局變量void InitMenuVal(void)WhereBackup_i = 0;ItemBackup_i = 0;Layer = 0;FatherIndexLayer+ = MenuTopIndex; /push index 待機(jī)界面作為起點(diǎn) QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)DispMenuTopUp()在CheckKey()中被調(diào)用之后,F(xiàn)lash變?yōu)榱?,那么如上所述CheckKey()函數(shù)發(fā)現(xiàn)Flash為1,會(huì)根據(jù)當(dāng)前所引號(hào)找出執(zhí)行函數(shù)來執(zhí)行的,當(dāng)前索引號(hào)在DispMenuTopUp調(diào)用

27、后變成了5,而5的執(zhí)行函數(shù)就是DispIcoMenuInit(),圖標(biāo)層的初始化函數(shù)。繼續(xù)追蹤代碼:void DispIcoMenuInit()ItemNum = IcoMenulanguage.TextNum;/多少數(shù)據(jù)項(xiàng)DispItem = IcoMenulanguage.Text; /數(shù)據(jù)GUI_Clear();/-if(Flash = FlashMode_AutoInit)/從0進(jìn)入,初始化Item等值PUSH();Item = 0;Where = 0;/菜單名字GUI_DispStringAtBar(*(DispItem+Item),0,ICO_PosY+ICO_YSize,126,

28、GUI_TA_HCENTER);GUI_DrawIcon(icosItem,ICO_PosX,ICO_PosY); /圖標(biāo)/顯示按鍵對(duì)應(yīng)的文字提示,1->"進(jìn)入"GUI_DispStringAtBar(*(Tiplanguage.Text+1),0,Enter_PosY,126,GUI_TA_HCENTER); Bar(Item,ItemNum,MenuBarPosX,MenuBarNumPosX); /維護(hù)滾動(dòng)條return;發(fā)現(xiàn)該函數(shù)顯示了菜單名字和圖標(biāo)等。界面到了下圖:需要留心的是這個(gè)函數(shù)中執(zhí)行了一個(gè)PSUH()的函數(shù),該函數(shù)的功能是備份當(dāng)前菜單的相關(guān)參數(shù),為從

29、子菜單返回父菜單時(shí),能還原原有顯示而服務(wù)。在圖標(biāo)層下當(dāng)前索引號(hào)是MenuIndex=5,圖標(biāo)層翻動(dòng)時(shí)是切換不同的文字顯示和圖標(biāo)的,并且維護(hù)Item變量。函數(shù)DispIcoMenuLeft()和函數(shù)DispIcoMenuRight()的最后都是調(diào)用 Jump2Menu(SelfMenuIndex,FlashMode_NoAction); FlashMode_NoAction是通知代碼不要做刷新屏幕的動(dòng)作,而宏SelfMenuIndex的定義在Menu.H中如下:#define SelfMenuIndex FatherIndexLayer-1也就是把當(dāng)前狀態(tài)索引號(hào)修正為備份數(shù)組FatherInde

30、x里的最后一個(gè)。void DispIcoMenuLeft()if(Item=0)Item = ItemNum-1;elseItem-;GUI_DispStringAtBar(*(DispItem+Item),0,ICO_PosY+ICO_YSize,126,GUI_TA_HCENTER);/菜單名字GUI_DrawIcon(icosItem,ICO_PosX,ICO_PosY); /圖標(biāo)Bar(Item,ItemNum,MenuBarPosX,MenuBarNumPosX); /維護(hù)滾動(dòng)條QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) Jump2Menu(SelfMenuIndex,

31、FlashMode_NoAction);在這里Jump2Menu(SelfMenuIndex)的調(diào)用使得KeyFuncIndex5,因?yàn)镻USH()函數(shù)的調(diào)用把MenuIndex=5備份了。也就是說不管如何翻動(dòng),當(dāng)前狀態(tài)索引號(hào)依然是KeyFuncIndex=5,CheckKey()函數(shù)一直根據(jù)狀態(tài)5來查詢,分發(fā)。 5, 6, 7, 8, 9,(*DispIcoMenuInit), /圖標(biāo)層菜單 6, 0, 0, 0, 0,(*DispIcoMenuUp), / 7, 0, 0, 0, 0,(*DispIcoMenuDown), / 8, 0, 0, 0, 0,(*DispIcoMenuLeft

32、), / 9, 0, 0, 0, 0,(*DispIcoMenuRight),/當(dāng)在圖標(biāo)層的按鍵輸入是Up時(shí),執(zhí)行的函數(shù)將有所不同,查看DispIcoMenuUp()函數(shù)就了解細(xì)節(jié)了。void DispIcoMenuUp()switch(Item)case 0:GUI_Clear();/功能Jump2Menu(MenuFuncIndex,FlashMode_AutoInit);return;case 1:GUI_Clear();/參數(shù)Jump2Menu(MenuParaIndex,FlashMode_AutoInit);return;case 2:GUI_Clear();/測(cè)量Jump2Men

33、u(MenuMeasureIndex,FlashMode_AutoInit);return;case 3:GUI_Clear();/語言Jump2Menu(MenuLanguageIndex,FlashMode_ManualInit);/在MenuLanguage.C中的DispMenuLanguageInit函數(shù)中修改Item Where! return;case 4:Jump2Menu(SelfMenuIndex,FlashMode_NoAction);return;case 5:Jump2Menu(SelfMenuIndex,FlashMode_NoAction);return;defa

34、ult:Jump2Menu(MenuTopIndex,FlashMode_NoAction);return;QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)該函數(shù)根據(jù)Item的值由Jump2Menu函數(shù)修正當(dāng)前狀態(tài)索引號(hào),并把Flash置為一個(gè)大于0的值,然后返回。我們已經(jīng)知道CheckKey()函數(shù)一旦發(fā)現(xiàn)Flash大于0,便會(huì)根據(jù)當(dāng)前索引號(hào)執(zhí)行對(duì)應(yīng)的功能函數(shù)的,因此,若是在“功能”下按了Up鍵,那么狀態(tài)跳轉(zhuǎn)到MenuFuncIndex=10。檢查MenuFSM.C中的表格:10,11,12,13,14,(*DispMenuFuncInit), /"功能"11,

35、0, 0, 0, 0,(*DispMenuFuncUp), /12, 0, 0, 0, 0,(*DispMenuFuncDown), /13, 0, 0, 0, 0,(*DispMenuFuncLeft), /14, 0, 0, 0, 0,(*DispMenuFuncRight),/ 于是執(zhí)行了DispMenuFuncInit()函數(shù)。/Bar型菜單void DispMenuFuncInit()GUI_Clear();BarMenu = &MenuFunclanguage;ItemNum = (*BarMenu).TextNum;DispItem = (*BarMenu).Text;/

36、顯示按鍵對(duì)應(yīng)的文字提示,1->"選擇"GUI_DispStringAtBar(*(Tiplanguage.Text+1),0,Enter_PosY,126,GUI_TA_HCENTER); /用戶定義的初始化代碼請(qǐng)放在這里BarMenuInit();/調(diào)用公共初始化的代碼該函數(shù)先清屏,依據(jù)當(dāng)前語言修改菜單結(jié)構(gòu)指針BarMenu;然后依據(jù)修改后的指針得到跟菜單顯示有關(guān)的2個(gè)變量ItemNum DispItem;顯示按鍵提示詞;最后調(diào)用了BarMenuInit()初始化整個(gè)條項(xiàng)層菜單。然后就看到了“功能”的條項(xiàng)層菜單。 需要注意BarMenuInit函數(shù)開始的部分代碼:i

37、f(Flash = FlashMode_AutoInit)/常規(guī)進(jìn)入 做備份PUSH();/在修改Item Where之前備份這些參數(shù)數(shù)據(jù)!Item = 0;Where = 0; else if (Flash = FlashMode_ManualInit)/非常規(guī)進(jìn)入 在之前已經(jīng)備份了,這里做邊界檢查if(Where > DispMin-1)/檢查是否出界/Where = DispMin-1;/A.最底部的顯示位置Where = 0; /B.最頂部的顯示位置if(Item > ItemNum-1)/檢查是否出界/Item = ItemNum-1;/A.最后的一個(gè)項(xiàng)Item = 0;

38、 /B.最開始的一個(gè)項(xiàng)Flash的值由父菜單的Up按鍵函數(shù)(這里是DispIcoMenuUp函數(shù))設(shè)置,在本菜單中檢查,通常我們只會(huì)把Flash設(shè)置為FlashMode_AutoInit,因此調(diào)用PUSH函數(shù)QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)備份當(dāng)前狀態(tài)號(hào)(這里當(dāng)前狀態(tài)號(hào)是10)。而如果父菜單的Up按鍵函數(shù)設(shè)置flash為FlashMode_ManualInit。那么這個(gè)Init函數(shù)將不太一樣。看語言選擇的Init函數(shù)。void DispMenuLanguageInit()GUI_Clear();/切換Bar顯示內(nèi)容BarMenu = &MenuLanguagel

39、anguage;ItemNum = (*BarMenu).TextNum;DispItem = (*BarMenu).Text;/用戶的初始化代碼請(qǐng)放在這里/顯示父菜單名字/顯示按鍵提示 2->OKGUI_DispStringAtBar(*(Tiplanguage.Text+2),0,Enter_PosY,126,GUI_TA_HCENTER);if(Flash = FlashMode_ManualInit)/首次進(jìn)入本層菜單,調(diào)整Item wherePUSH();Item = language;Where = Item;/公共初始化部分BarMenuInit();在進(jìn)入該函數(shù)前,函數(shù)D

40、ispIcoMenuUp已經(jīng)把flash設(shè)置為2,函數(shù)DispMenuLanguageInit將依據(jù)當(dāng)前語言調(diào)整首次進(jìn)入時(shí),高亮項(xiàng)的位置,比如當(dāng)前語言是中文,那么進(jìn)入語言菜單時(shí)是這樣:而如果當(dāng)前語言是英文,那么進(jìn)入語言菜單時(shí)是這樣:FlashMode_ManualInit的設(shè)置使得代碼可以控制進(jìn)入菜單時(shí)高亮在哪個(gè)項(xiàng)上,對(duì)于語言選擇等一些方面有一定提示的作用?;氐皆瓉淼姆治鲋?,我們接下來開始分析在條項(xiàng)層菜單下,4個(gè)按鍵的全部行為,條項(xiàng)層的顯示內(nèi)容基本上時(shí)固定的不變的,一個(gè)條項(xiàng)層的屬性可以歸結(jié)為:DispItem 指向顯示內(nèi)容數(shù)組開始位置的指針I(yè)tem 當(dāng)前顯示條項(xiàng)在顯示內(nèi)容數(shù)組中的偏置QQ 64

41、134703符串在液晶上。 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) Where 當(dāng)前顯示條項(xiàng)在液晶上的位置 由DispItem和Item就知道了需要顯示的字符串,根據(jù)Where我們可以顯示該字在條項(xiàng)層菜單中翻動(dòng)時(shí)函數(shù)MenuNameLeft和函數(shù)MenuNameRight分別調(diào)用BarMenuLeft()和BarMenuRight來維護(hù)的Item和Where。void DispMenuFuncLeft()BarMenuLeft();void DispMenuFuncRight()BarMenuRight();在本層菜單中按向左鍵后,MenuFuncIndex根據(jù)查表,由10變?yōu)榕R時(shí)的13,執(zhí)行Dis

42、pMenuFuncLeft函數(shù),該函數(shù)調(diào)用的BarMenuLeft在退出前,調(diào)用Jump2Menu(SelfMenuIndex),把當(dāng)前狀態(tài)號(hào)重新改回10。按向右鍵后,MenuFuncIndex根據(jù)查表,由10變?yōu)榕R時(shí)的14,執(zhí)行DispMenuFuncRight函數(shù),該函數(shù)退出前,該函數(shù)調(diào)用的BarMenuRight 在退出前,調(diào)用Jump2Menu(SelfMenuIndex),把當(dāng)前狀態(tài)號(hào)重新改回10。也就是說不管是函數(shù)BarMenuLeft 還是函數(shù)BarMenuRight ,在其末尾均調(diào)用Jump2Menu(SelfMenuIndex);來恢復(fù)到DispMenuFuncInit函數(shù)所

43、在的索引號(hào)10。因此不管按向左向右鍵都會(huì)回到MenuFuncIndex=10來重新分發(fā)的。當(dāng)按鍵是向上時(shí),調(diào)用DispMenuFuncUp,根據(jù)Item號(hào)來修改當(dāng)前狀態(tài)索引號(hào),進(jìn)入一個(gè)子菜單中;或者根據(jù)Item號(hào)來執(zhí)行實(shí)際的功能代碼。代碼跟函數(shù)DispIcoMenuUp相似。當(dāng)按鍵是向下時(shí),調(diào)用DispMenuFuncDown,調(diào)用POP,得到原來已經(jīng)壓入堆棧的父菜單的狀態(tài)索引號(hào),并把ReFlash置為1,通知CheckKey()調(diào)用函數(shù)恢復(fù)父菜單的顯示。至此,圖標(biāo)層、條項(xiàng)型菜單分析已經(jīng)很完整。模版代碼講解 在MenuPara.C中有常見用法的模版代碼:/* 菜單使用例程0.Jump2Menu

44、 + FlashMode_AutoInit/FlashMode_ManualInit跳轉(zhuǎn)到任意菜單,FlashMode_AutoInit->在BarMenuInit函數(shù)中執(zhí)行PUSH;FlashMode_ManualInit->子菜單的Init函數(shù)中PUSH,看例子:DispMenuLanguageInit1.PUSH + POP執(zhí)行一些功能,并使用LCD后,回到原有界面,回到原有界面-包括反顯位置都恢復(fù)2.Jump2Menu(SelfMenuIndex,FlashMode_ReFlash);執(zhí)行一些功能,并使用LCD后,執(zhí)行如上調(diào)用,回到原有界面-包括反顯位置都恢復(fù)QQ 6413

45、4703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)3.POP執(zhí)行一些功能,并使用LCD后,回到上層菜單,恢復(fù)上層界面4.Jump2Menu(SelfMenuIndex,FlashMode_NoAction);執(zhí)行一定功能后,但不占用LCD的話,直接界面不動(dòng)* */void DispMenuParaUp()switch(Item)case 0:/Jump2MenuGUI_Clear();GUI_DispStringAt("Do Something nthen Back to nTop Menu!",0,0); GUI_Delay(4000);Jump2Menu(MenuTopInde

46、x,FlashMode_AutoInit);break;case 1:/PUSH ->POPPUSH();GUI_Clear();GUI_DispStringAt("Do Something nthen Back to nThis Menu!",0,0); GUI_Delay(4000);POP();break;case 2:/ReFlash = 1GUI_Clear();GUI_DispStringAt("Do Something nthen Back to nThis Menu!",0,0); GUI_Delay(4000);Jump2Menu

47、(SelfMenuIndex,FlashMode_ReFlash);break;case 3:/POPGUI_Clear();GUI_DispStringAt("Do Something nthen Back to nFather Menu!",0,0); GUI_Delay(4000);POP();break;case 4:/No ReFlash/No Action Here!/Or The Action no need the LCD DispJump2Menu(SelfMenuIndex,FlashMode_NoAction);break;default:Jump2M

48、enu(SelfMenuIndex,FlashMode_NoAction);return;以下給出執(zhí)行效果圖。0: 執(zhí)行一些函數(shù)調(diào)用后返回待機(jī)界面(當(dāng)然也可以跳轉(zhuǎn)到任意一個(gè)菜單)。QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)ààà1 2:執(zhí)行一些函數(shù)調(diào)用后返回本菜單,原有界面被恢復(fù)。àà à3執(zhí)行一些函數(shù)調(diào)用后,回到本菜單的父菜單。àààQQ 64134703一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) 動(dòng)態(tài)內(nèi)容層菜單由于動(dòng)態(tài)內(nèi)容層代碼不是很完善,因此不在這里分析,如果需要了解看MenuClock.C,里

49、面有一個(gè)可用的原型。à à簡(jiǎn)單講講思路:函數(shù)DispMenuClockLeft()和函數(shù) DispMenuClockRight()在維護(hù)Item后,調(diào)用函數(shù)FlashDisp(),該函數(shù)根據(jù)Item顯示標(biāo)題,并調(diào)用函數(shù)得到Item對(duì)應(yīng)的動(dòng)態(tài)內(nèi)容,顯示之。也要留意函數(shù)DispMenuClockInit()里面是如何顯示顯示第一次的內(nèi)容的,又是如何在進(jìn)入子菜單后,刷新顯示的。動(dòng)態(tài)生成條項(xiàng)菜單內(nèi)容在搭建的代碼框架中,條項(xiàng)菜單的顯示內(nèi)容通常是固定不變的,但也有些場(chǎng)合需要?jiǎng)討B(tài)產(chǎn)生這些條項(xiàng)內(nèi)容,比如說手機(jī)短信收件箱里,就是依照收到的短信的發(fā)送人名字生成條項(xiàng)的。在MenuFunc.C中有

50、一個(gè)動(dòng)態(tài)生成條項(xiàng)的例子代碼,由于內(nèi)容的動(dòng)態(tài)產(chǎn)生因此需要一些RAM來存放動(dòng)態(tài)項(xiàng)。#define DataItemSize 8U8 DataItemDispMaxDataItemSize="DataX ","DataX ","DataX ",;U8 *_CONST_ DataItem_p=DataItem0,DataItem1,DataItem2QQ 64134703; 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)該范例中,當(dāng)上下翻轉(zhuǎn)時(shí),void DispMenuDataLeft()和void DispMenuDataRight()動(dòng)態(tài)修改DataX

51、,X是一個(gè)數(shù)字。依照一樣的原理,可以在這兩個(gè)函數(shù)中完成得到動(dòng)態(tài)顯示內(nèi)容,然后修改顯示緩沖DataItem。à動(dòng)態(tài)生成條項(xiàng)菜單要占用的RAM大概就是DataItem數(shù)組占據(jù)的內(nèi)存大小,這個(gè)大小跟LCD一屏可以顯示多少個(gè)條項(xiàng)DispMax有關(guān)、跟一個(gè)條項(xiàng)內(nèi)容的字符大小DataItemSize有關(guān)。數(shù)字快捷方式的實(shí)現(xiàn) 數(shù)字快捷方式的意思是根據(jù)條項(xiàng)的編號(hào),直接用數(shù)字鍵輸入該編號(hào),然后跳轉(zhuǎn)到該子菜單中,在Nokia手機(jī)中這樣的功能,只要添加如下幾行代碼到MenuFSM.C的U8 CheckKey(void)函數(shù)中便能實(shí)現(xiàn)這種功能。當(dāng)然該功能需要Key = KeyScan();能返回?cái)?shù)字按鍵的鍵

52、值。在Menu.H中有對(duì)應(yīng)的宏開關(guān)來打開/關(guān)閉該功能。 /*2006/09/08 數(shù)字鍵做快捷方式輸入1.判別數(shù)字鍵值是否小于ItemNum-1 否則是無效快捷方式2.有效快捷方式下,把鍵值給Item,調(diào)用Key_Up的處理代碼3.需要添加超時(shí)處理,超時(shí)了就不能使用?(需要么?不需要么?)*/case Key_1:case Key_2:case Key_3:case Key_4:case Key_5:case Key_6:case Key_7:case Key_8:case Key_9:Key = chang_code(Key);if(Key - '1') <= Item

53、Num-1)Item = Key - '1'/如果需要顯示的項(xiàng)比可以顯示的項(xiàng)少,那么修正Where 否則默認(rèn)Where為0if(ItemNum <= DispMax)Where = Item;elseWhere = 0;QQ 64134703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)/- KeyFuncIndex=KeyTabKeyFuncIndex.KeyUpState; KeyFuncPtr=KeyTabKeyFuncIndex.CurrentOperate; (*KeyFuncPtr)();/執(zhí)行當(dāng)前按鍵的操作/- else IsKey = 0;break;QQ 64134

54、703 一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn)菜單函數(shù)調(diào)用圖圖10函數(shù)調(diào)用圖QQ 64134703一個(gè)占用內(nèi)存極少的菜單系統(tǒng)的實(shí)現(xiàn) 問答FAQ這個(gè)東西哪來的?2005年3月份是從事一個(gè)手持儀器的開發(fā),那時(shí)發(fā)覺系統(tǒng)需要管理的內(nèi)容很多,為了有效管理,決定設(shè)計(jì)一個(gè)菜單程序,那時(shí)我的手機(jī)是Nokia3315,于是開始研究這個(gè)手機(jī)的行為,思考實(shí)現(xiàn)方法,項(xiàng)目完工后,便有了這個(gè)第一個(gè)版本,后來把很多身邊朋友的手機(jī)都認(rèn)真的看了個(gè)遍,思考它們的異同、實(shí)現(xiàn)機(jī)理,然后再做了許多代碼優(yōu)化和修改,使得更易于移植,更有通用性。對(duì)很多手機(jī)菜單,不單單手機(jī)的菜單,很多儀器菜單,留心觀察后,覺得文章中的總結(jié)是基本上對(duì)的,而提出的實(shí)現(xiàn)方法也可行,可以適應(yīng)多種情況。當(dāng)然這只是我想到的一個(gè)實(shí)現(xiàn)的方法,相信也有其它可以實(shí)現(xiàn)的方法。其中關(guān)于FSM的那部分代碼,最早在2003年剛開始學(xué)習(xí)C51時(shí)在C51BBS上見過類似的,不過當(dāng)時(shí)沒有看懂,我這里也是借用了思路,我想我的貢獻(xiàn)應(yīng)該是實(shí)現(xiàn)條項(xiàng)函數(shù)和菜單周轉(zhuǎn)時(shí)PUSH、POP的代碼等。能在51這種低速CPU上跑不?這個(gè)程序的代碼原本是在一個(gè)使用SM89C58的項(xiàng)目上使用的,內(nèi)存僅僅256Byte,F(xiàn)lash32

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論