螢幕乃嵌入式系統生存之重要輔助,面目可憎之顯示將另使用者逃之夭夭。螢幕程式設計若處理不好,將是軟體中最不系統、最混亂的部分,筆者曾深受其害。
漢字處理
現在要解決的問題是,嵌入式系統中經常要使用的並非是完整的漢字型檔,往往只是需要提供數量有限的漢字供必要的顯示功能。例如,乙個微波爐的lcd上沒有必要提供顯示"電子郵件"的功能;乙個提供漢字顯示功能的空調的lcd上不需要顯示一條"短訊息",諸如此類。但是一部手機、小靈通則通常需要包括較完整的漢字型檔。
如果包括的漢字型檔較完整,那麼,由內碼計算出漢字字模在庫中的偏移是十分簡單的:漢字型檔是按照區位的順序排列的,前乙個位元組為該漢字的區號,後乙個位元組為該字的位號。每乙個區記錄94個漢字,位號則為該字在該區中的位置。因此,漢字在漢字型檔中的具體位置計算公式為:94*(區號-1)+位號-1。減1是因為陣列是以0為開始而區號位號是以1為開始的。只需乘上乙個漢字字模占用的位元組數即可,即:(94*(區號-1)+位號-1)*乙個漢字字模占用位元組數,以16*16點陣字型檔為例,計算公式則為:(94*(區號-1)+(位號-1))*32。漢字型檔中從該位置起的32位元組資訊記錄了該字的字模資訊。
對於包含較完整漢字型檔的系統而言,我們可以以上述規則計算字模的位置。但是如果僅僅是提供少量漢字呢?譬如幾十至幾百個?最好的做法是:
定義巨集:
# define ex_font_char(value)
# define ex_font_unicode_val(value) (value),
# define ex_font_ansi_val(value) (value),
定義結構體:
typedef struct _wide_unicode_font16x16
unicode;
#define chinese_char_num … /* 漢字數量 */
字模的儲存用陣列:
unicode chinese[chinese_char_num] =
},},},}
} 要顯示特定漢字的時候,只需要從陣列中查詢內碼與要求漢字內碼相同的即可獲得字模。如果前面的漢字在陣列中以內碼大小順序排列,那麼可以以二分查詢法更高效的查詢到漢字的字模。
這是一種很有效的組織小漢字型檔的方法,它可以保證程式有很好的結構。
系統時間顯示
從nvram中可以讀取系統的時間,系統一般借助nvram產生的秒中斷每秒讀取一次當前時間並在lcd上顯示。關於時間的顯示,有乙個效率問題。因為時間有其特殊性,那就是60秒才有一次分鐘的變化,60分鐘才有一次小時變化,如果我們每次都將讀取的時間在螢幕上完全重新重新整理一次,則浪費了大量的系統時間。
乙個較好的辦法是我們在時間顯示函式中以靜態變數分別儲存小時、分鐘、秒,只有在其內容發生變化的時候才更新其顯示。
extern void displaytime(…)
if(bynewminute!= byminute)
if(bynewsecond!= bysecond)}
這個例子也可以順便作為c語言中static關鍵字強大威力的證明。當然,在c++語言裡,static具有了更加強大的威力,它使得某些資料和函式脫離"物件"而成為"類"的一部分,正是它的這一特點,成就了軟體的無數優秀設計。
動畫顯示
動畫是無所謂有,無所謂無的,靜止的畫面走的路多了,也就成了動畫。隨著時間的變更,在螢幕上顯示不同的靜止畫面,即是動畫之本質。所以,在乙個嵌入式系統的lcd上欲顯示動畫,必須借助定時器。沒有硬體或軟體定時器的世界是無法想像的:
(1) 沒有定時器,乙個作業系統將無法進行時間片的輪轉,於是無法進行多工的排程,於是便不再成其為乙個多工作業系統;
(3) 沒有定時器,乙個網路協議將無法運轉,因為其無法獲知何時包傳輸超時並重傳之,無法在特定的時間完成特定的任務。
因此,沒有定時器將意味著沒有作業系統、沒有網路、沒有多**,這將是怎樣的黑暗?所以,合理並靈活地使用各種定時器,是對乙個軟體人的最基本需求!
在80186為主晶元的嵌入式系統中,我們需要借助硬體定時器的中斷來作為軟體定時器,在中斷發生後變更畫面的顯示內容。在時間顯示"xx:xx"中讓冒號交替有無,每次秒中斷發生後,需呼叫showdot:
void showdot()
else
bshowdot = ! bshowdot;}
選單操作
無數人為之絞盡腦汁的問題終於出現了,在這一節裡,我們將看到,在c語言中哪怕用到一丁點的物件導向思想,軟體結構將會有何等的改觀!
筆者曾經是個笨蛋,被選單搞暈了,給出這樣的乙個系統:
圖1 選單範例
要求以鍵盤上的"← →"鍵切換選單焦點,當使用者在焦點處於某選單時,若敲擊鍵盤上的ok、cancel鍵則呼叫該焦點擊單對應之處理函式。我曾經傻傻地這樣做著:
/* 按下ok鍵 */
void onokkey()
}/* 按下cancel鍵 */
void oncancelkey()}
終於有一天,我這樣做了:
/* 將選單的屬性和操作"封裝"在一起 */
typedef struct tagsy**enu
sy**enu, *lpsy**enu;
當我定義選單時,只需要這樣:
static sy**enu menu[menu_num] =,,
,…};
ok鍵和cancel鍵的處理變成:
/* 按下ok鍵 */
void onokkey()
/* 按下cancel鍵 */
void oncancelkey()
程式被大大簡化了,也開始具有很好的可擴充套件性!我們僅僅利用了物件導向中的封裝思想,就讓程式結構清晰,其結果是幾乎可以在無需修改程式的情況下在系統中新增更多的選單,而系統的按鍵處理函式保持不變。
物件導向,真神了!
模擬messagebox函式
messagebox函式,這個windows程式設計中的超級猛料,不知道是多少入門者第一次用到的函式。還記得我們第一次在windows中利用messagebox輸出 "hello,world!"對話方塊時新奇的感覺嗎?無法統計,這個世界上究竟有多少程式設計師學習windows程式設計是從messagebox("hello,world!",…)開始的。在我本科的學校,廣泛流傳著乙個詞彙,叫做"』hello,world』級程式設計師",意指入門級程式設計師,但似乎"』hello,world』級"這個說法更搞笑而形象。
圖2 經典的hello,world!
圖2給出了兩種永恆經典的hello,world對話方塊,一種只具有"確定",一種則包含"確定"、"取消"。是的,messagebox的確有,而且也應該有兩類!這完全是由特定的應用需求決定的。
嵌入式系統中沒有給我們提供messagebox,但是鑑於其功能強大,我們需要模擬之,乙個模擬的messagebox函式為:
/******************************************
/* 函式名稱: messagebox
/* 功能說明: 彈出式對話方塊,顯示提醒使用者的資訊
/* 引數說明: lpstr --- 提醒使用者的字串輸出資訊
/* type --- 輸出格式(id_ok = 0, id_okcancel = 1)
/* 返回值: 返回對話方塊接收的鍵值,只有兩種 key_ok, key_cancel
/******************************************
typedef enum type msg_type;
extern byte messagebox(lpbyte lpstr, byte type)
drawrect(0, 0, 239, ypos+high+16+4); /* 繪製外框 */
/* messagebox是模式對話方塊,阻塞執行,等待按鍵 */
while( (keyvalue != key_ok) || (keyvalue != key_cancel) )
/* 返回按鍵型別 */
if(keyvalue== key_ok)
else}
上述函式與我們平素在vc++等中使用的messagebox是何等的神似啊?實現這個函式,你會看到它在嵌入式系統中的妙用是無窮的。
總結
本篇是本系列文章中技巧性最深的一篇,它提供了嵌入式系統螢幕顯示方面一些很巧妙的處理方法,靈活使用它們,我們將不再被lcd上凌亂不堪的顯示內容所困擾。
螢幕乃嵌入式系統生存之重要輔助,面目可憎之顯示將另使用者逃之夭夭。螢幕程式設計若處理不好,將是軟體中最不系統、最混亂的部分,筆者曾深受其害。
C語言嵌入式系統程式設計修煉(三)
c語言嵌入式系統程式設計修煉 三 使用巨集定義在c 語言中,巨集是產生內嵌 的唯一方法。對於嵌入式系統而言,為了能達到效能要求,巨集是一種很好的代替函式的方法。寫乙個 標準 巨集 min 這個巨集輸入兩個引數並返回較小的乙個 錯誤做法 define min a,b a b a b 正確做法 defi...
C語言嵌入式系統程式設計修煉之螢幕操作
漢字處理 現在要解決的問題是,嵌入式系統中經常要使用的並非是完整的漢字型檔,往往只是需要提供數量有限的漢字供必要的顯示功能。例如,乙個微波爐的lcd上沒有必要提供顯示 電子郵件 的功能 乙個提供漢字顯示功能的空調的lcd上不需要顯示一條 短訊息 諸如此類。但是一部 手機 小靈通則通常需要包括較完整的...
C語言嵌入式系統程式設計修煉之螢幕操作
c語言嵌入式系統程式設計修煉之螢幕操作 出處 天極網 2005 06 20 15 54 現在要解決的問題是,嵌入式系統中經常要使用的並非是完整的漢字型檔,往往只是需要提供數量有限的漢字供必要的顯示功能 漢字處理 現在要解決的問題是,嵌入式系統中經常要使用的並非是完整的漢 字型檔,往往只是需要提供數量...