字模的存儲(chǔ)用數(shù)組:
Unicode chinese[CHINESE_CHAR_NUM] =
{
{
EX_FONT_CHAR(“業(yè)”)
EX_FONT_UNICODE_VAL(0x4e1a)
{0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x44, 0x44, 0x46, 0x24, 0x4c, 0x24, 0x48, 0x14, 0x50, 0x1c, 0x50, 0x14, 0x60, 0x04, 0x40, 0x04, 0x40, 0x04, 0x44, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00}
},
{
EX_FONT_CHAR(“中”)
EX_FONT_UNICODE_VAL(0x4e2d)
{0x01, 0x00, 0x01, 0x00, 0x21, 0x08, 0x3f, 0xfc, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08, 0x21, 0x08,
0x3f, 0xf8, 0x21, 0x08, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}
},
{
EX_FONT_CHAR(“云”)
EX_FONT_UNICODE_VAL(0x4e91)
{0x00, 0x00, 0x00, 0x30, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xff, 0xfe, 0x03, 0x00, 0x07, 0x00,
0x06, 0x40, 0x0c, 0x20, 0x18, 0x10, 0x31, 0xf8, 0x7f, 0x0c, 0x20, 0x08, 0x00, 0x00}
},
{
EX_FONT_CHAR(“件”)
EX_FONT_UNICODE_VAL(0x4ef6)
{0x10, 0x40, 0x1a, 0x40, 0x13, 0x40, 0x32, 0x40, 0x23, 0xfc, 0x64, 0x40, 0xa4, 0x40, 0x28, 0x40, 0x2f, 0xfe,
0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40}
}
}
要顯示特定漢字的時(shí)候,只需要從數(shù)組中查找內(nèi)碼與要求漢字內(nèi)碼相同的即可獲得字模。如果前面的漢字在數(shù)組中以內(nèi)碼大小順序排列,那么可以以二分查找法更高效的查找到漢字的字模。
這是一種很有效的組織小漢字庫(kù)的方法,它可以保證程序有很好的結(jié)構(gòu)。
系統(tǒng)時(shí)間顯示
從NVRAM中可以讀取系統(tǒng)的時(shí)間,系統(tǒng)一般借助NVRAM產(chǎn)生的秒中斷每秒讀取一次當(dāng)前時(shí)間并在LCD上顯示。關(guān)于時(shí)間的顯示,有一個(gè)效率問(wèn)題。因?yàn)闀r(shí)間有其特殊性,那就是60秒才有一次分鐘的變化,60分鐘才有一次小時(shí)變化,如果我們每次都將讀取的時(shí)間在屏幕上完全重新刷新一次,則浪費(fèi)了大量的系統(tǒng)時(shí)間。
一個(gè)較好的辦法是我們?cè)跁r(shí)間顯示函數(shù)中以靜態(tài)變量分別存儲(chǔ)小時(shí)、分鐘、秒,只有在其內(nèi)容發(fā)生變化的時(shí)候才更新其顯示。
extern void DisplayTime(…)
{
static BYTE byHour,byMinute,bySecond;
BYTE byNewHour, byNewMinute, byNewSecond;
byNewHour = GetSysHour();
byNewMinute = GetSysMinute();
byNewSecond = GetSysSecond();
if(byNewHour!= byHour)
{
… /* 顯示小時(shí) */
byHour = byNewHour;
}
if(byNewMinute!= byMinute)
{
… /* 顯示分鐘 */
byMinute = byNewMinute;
}
if(byNewSecond!= bySecond)
{
… /* 顯示秒鐘 */
bySecond = byNewSecond;
}
}
這個(gè)例子也可以順便作為C語(yǔ)言中static關(guān)鍵字強(qiáng)大威力的證明。當(dāng)然,在C++語(yǔ)言里,static具有了更加強(qiáng)大的威力,它使得某些數(shù)據(jù)和函數(shù)脫離“對(duì)象”而成為“類”的一部分,正是它的這一特點(diǎn),成就了軟件的無(wú)數(shù)優(yōu)秀設(shè)計(jì)。
動(dòng)畫顯示
動(dòng)畫是無(wú)所謂有,無(wú)所謂無(wú)的,靜止的畫面走的路多了,也就成了動(dòng)畫。隨著時(shí)間的變更,在屏幕上顯示不同的靜止畫面,即是動(dòng)畫之本質(zhì)。所以,在一個(gè)嵌入式系統(tǒng)的LCD上欲顯示動(dòng)畫,必須借助定時(shí)器。沒(méi)有硬件或軟件定時(shí)器的世界是無(wú)法想像的:
(1) 沒(méi)有定時(shí)器,一個(gè)操作系統(tǒng)將無(wú)法進(jìn)行時(shí)間片的輪轉(zhuǎn),于是無(wú)法進(jìn)行多任務(wù)的調(diào)度,于是便不再成其為一個(gè)多任務(wù)操作系統(tǒng);
(2) 沒(méi)有定時(shí)器,一個(gè)多媒體播放軟件將無(wú)法運(yùn)作,因?yàn)樗恢篮螘r(shí)應(yīng)該切換到下一幀畫面;
(3) 沒(méi)有定時(shí)器,一個(gè)網(wǎng)絡(luò)協(xié)議將無(wú)法運(yùn)轉(zhuǎn),因?yàn)槠錈o(wú)法獲知何時(shí)包傳輸超時(shí)并重傳之,無(wú)法在特定的時(shí)間完成特定的任務(wù)。
因此,沒(méi)有定時(shí)器將意味著沒(méi)有操作系統(tǒng)、沒(méi)有網(wǎng)絡(luò)、沒(méi)有多媒體,這將是怎樣的黑暗?所以,合理并靈活地使用各種定時(shí)器,是對(duì)一個(gè)軟件人的最基本需求!
在80186為主芯片的嵌入式系統(tǒng)中,我們需要借助硬件定時(shí)器的中斷來(lái)作為軟件定時(shí)器,在中斷發(fā)生后變更畫面的顯示內(nèi)容。在時(shí)間顯示“xx:xx”中讓冒號(hào)交替有無(wú),每次秒中斷發(fā)生后,需調(diào)用ShowDot:
void ShowDot()
{
static BOOL bShowDot = TRUE; /* 再一次領(lǐng)略static關(guān)鍵字的威力 */
if(bShowDot)
{
showChar(’:’,xPos,yPos);
}
else
{
showChar(’ ’,xPos,yPos);
}
bShowDot = ! bShowDot;
}
菜單操作
無(wú)數(shù)人為之絞盡腦汁的問(wèn)題終于出現(xiàn)了,在這一節(jié)里,我們將看到,在C語(yǔ)言中哪怕用到一丁點(diǎn)的面向?qū)ο笏枷耄浖Y(jié)構(gòu)將會(huì)有何等的改觀!
要求以鍵盤上的“← →”鍵切換菜單焦點(diǎn),當(dāng)用戶在焦點(diǎn)處于某菜單時(shí),若敲擊鍵盤上的OK、CANCEL鍵則調(diào)用該焦點(diǎn)菜單對(duì)應(yīng)之處理函數(shù)。我曾經(jīng)傻傻地這樣做著:
/* 按下OK鍵 */
void onOkKey()
{
/* 判斷在什么焦點(diǎn)菜單上按下Ok鍵,調(diào)用相應(yīng)處理函數(shù) */
Switch(currentFocus)
{
case MENU1:
menu1OnOk();
break;
case MENU2:
menu2OnOk();
break;
…
}
}
/* 按下Cancel鍵 */
void onCancelKey()
{
/* 判斷在什么焦點(diǎn)菜單上按下Cancel鍵,調(diào)用相應(yīng)處理函數(shù) */
Switch(currentFocus)
{
case MENU1:
menu1OnCancel();
break;
case MENU2:
menu2OnCancel();
break;
…
}
}
終于有一天,我這樣做了:
/* 將菜單的屬性和操作“封裝”在一起 */
typedef struct tagSysMenu
{
char *text; /* 菜單的文本 */
BYTE xPos; /* 菜單在LCD上的x坐標(biāo) */
BYTE yPos; /* 菜單在LCD上的y坐標(biāo) */
void (*onOkFun)(); /* 在該菜單上按下ok鍵的處理函數(shù)指針 */
void (*onCancelFun)(); /* 在該菜單上按下cancel鍵的處理函數(shù)指針 */
}SysMenu, *LPSysMenu;
當(dāng)我定義菜單時(shí),只需要這樣:
static SysMenu menu[MENU_NUM] =
{
{
“menu1”, 0, 48, menu1OnOk, menu1OnCancel
}
,
{
“ menu2”, 7, 48, menu2OnOk, menu2OnCancel
}
,
{
“ menu3”, 7, 48, menu3OnOk, menu3OnCancel
}
,
{
“ menu4”, 7, 48, menu4OnOk, menu4OnCancel
}
…
};
OK鍵和CANCEL鍵的處理變成:
/* 按下OK鍵 */
void onOkKey()
{
menu[currentFocusMenu].onOkFun();
}
/* 按下Cancel鍵 */
void onCancelKey()
{
menu[currentFocusMenu].onCancelFun();
}
程序被大大簡(jiǎn)化了,也開(kāi)始具有很好的可擴(kuò)展性!我們僅僅利用了面向?qū)ο笾械姆庋b思想,就讓程序結(jié)構(gòu)清晰,其結(jié)果是幾乎可以在無(wú)需修改程序的情況下在系統(tǒng)中添加更多的菜單,而系統(tǒng)的按鍵處理函數(shù)保持不變。
面向?qū)ο螅嫔窳耍?/p>
模擬MessageBox函數(shù)
MessageBox函數(shù),這個(gè)Windows編程中的超級(jí)猛料,不知道是多少入門者第一次用到的函數(shù)。還記得我們第一次在Windows中利用MessageBox輸出 “Hello,World!”對(duì)話框時(shí)新奇的感覺(jué)嗎?無(wú)法統(tǒng)計(jì),這個(gè)世界上究竟有多少程序員學(xué)習(xí)Windows編程是從MessageBox(“Hello,World!”,…)開(kāi)始的。在我本科的學(xué)校,廣泛流傳著一個(gè)詞匯,叫做“’Hello,World’級(jí)程序員”,意指入門級(jí)程序員,但似乎“’Hello,World’級(jí)”這個(gè)說(shuō)法更搞笑而形象。
嵌入式系統(tǒng)中沒(méi)有給我們提供MessageBox,但是鑒于其功能強(qiáng)大,我們需要模擬之,一個(gè)模擬的MessageBox函數(shù)為:
/******************************************
/* 函數(shù)名稱: MessageBox
/* 功能說(shuō)明: 彈出式對(duì)話框,顯示提醒用戶的信息
/* 參數(shù)說(shuō)明: lpStr --- 提醒用戶的字符串輸出信息
/* TYPE --- 輸出格式(ID_OK = 0, ID_OKCANCEL = 1)
/* 返回值: 返回對(duì)話框接收的鍵值,只有兩種 KEY_OK, KEY_CANCEL
/******************************************
typedef enum TYPE { ID_OK,ID_OKCANCEL }MSG_TYPE;
extern BYTE MessageBox(LPBYTE lpStr, BYTE TYPE)
{
BYTE key = -1;
ClearScreen(); /* 清除屏幕 */
DisplayString(xPos,yPos,lpStr,TRUE); /* 顯示字符串 */
/* 根據(jù)對(duì)話框類型決定是否顯示確定、取消 */
switch (TYPE)
{
case ID_OK:
DisplayString(13,yPos+High+1, “ 確定 ”, 0);
break;
case ID_OKCANCEL:
DisplayString(8, yPos+High+1, “ 確定 ”, 0);
DisplayString(17,yPos+High+1, “ 取消 ”, 0);
break;
default:
break;
}
DrawRect(0, 0, 239, yPos+High+16+4); /* 繪制外框 */
/* MessageBox是模式對(duì)話框,阻塞運(yùn)行,等待按鍵 */
while( (key != KEY_OK) || (key != KEY_CANCEL) )
{
key = getSysKey();
}
/* 返回按鍵類型 */
if(key== KEY_OK)
{
return ID_OK;
}
else
{
return ID_CANCEL;
}
}
上述函數(shù)與我們平素在VC++等中使用的MessageBox是何等的神似啊?實(shí)現(xiàn)這個(gè)函數(shù),你會(huì)看到它在嵌入式系統(tǒng)中的妙用是無(wú)窮的。
評(píng)論
查看更多