到目前為止,似乎如果我們要想做一個(gè)電話號(hào)碼記事本之類的電子助手已經(jīng)萬(wàn)事俱備了,但真正開(kāi)始做的時(shí)候才發(fā)現(xiàn),我們還沒(méi)有教會(huì)AVR如何去寫字。如果說(shuō),我們前面已經(jīng)能在LCD上畫出“壁畫”的話,那么要想讓別人看懂你記錄的到底是什么鬼畫符還需要一點(diǎn)點(diǎn)關(guān)于“甲骨文”的掃盲。事實(shí)上,大家約定俗成的固定大小的圖片集或其子集就是一個(gè)被尊稱為字庫(kù)的神圣典籍。在這個(gè)圣經(jīng)里面記錄的是一種被稱之為“字模碼”的東西,對(duì)于我們,這種信息可能相當(dāng)抽象,但是借助LCD,那么字模碼就是一個(gè)我們能看懂的字符在顯存中存在的模式。
不得不承認(rèn),到目前為止,似乎如果我們要想做一個(gè)電話號(hào)碼記事本之類的電子助手已經(jīng)萬(wàn)事俱備了,但真正開(kāi)始做的時(shí)候才發(fā)現(xiàn),我們還沒(méi)有教會(huì)AVR如何去寫字。如果說(shuō),我們前面已經(jīng)能在LCD上畫出“壁畫”的話,那么要想讓別人看懂你記錄的到底是什么鬼畫符還需要一點(diǎn)點(diǎn)關(guān)于“甲骨文”的掃盲。事實(shí)上,大家約定俗成的固定大小的圖片集或其子集就是一個(gè)被尊稱為字庫(kù)的神圣典籍。在這個(gè)圣經(jīng)里面記錄的是一種被稱之為“字模碼”的東西,對(duì)于我們,這種信息可能相當(dāng)抽象,但是借助LCD,那么字模碼就是一個(gè)我們能看懂的字符在顯存中存在的模式。
關(guān)于這些字模碼是如何排列的,自古以來(lái)就有數(shù)不清的模式。終于有一天,一群中國(guó)人伴隨著新中國(guó)站了起來(lái),制定了一個(gè)叫做國(guó)標(biāo)的標(biāo)準(zhǔn)(GB),根據(jù)這個(gè)標(biāo)準(zhǔn),祖國(guó)大地的字模碼才有了統(tǒng)一的目錄,而查詢這個(gè)目錄的方法已經(jīng)逐漸被人們所淡忘,吹落那源自電報(bào)碼的書(shū)籍紅色封皮上的滄桑,用手輕輕撫摸封皮上的的文字:“區(qū)位碼”,我們發(fā)現(xiàn),其實(shí)他包含了6000個(gè)漢字的一級(jí)字庫(kù)其他一些由非常用字組成的多級(jí)字庫(kù)。
在西方,埃尼阿克的故鄉(xiāng),一群依靠技術(shù)侵略世界的瘋子根據(jù)自己半通不同的習(xí)慣制定了一個(gè)由128個(gè)字符組成的交換標(biāo)準(zhǔn)稱之為ASCII碼,由于技術(shù)大潮的沖擊,世界妥協(xié)了。
這一切的一切都無(wú)法改變字庫(kù)只不過(guò)是圖片集和的本質(zhì)。所以,敢于抵抗強(qiáng)權(quán)的人們?cè)谧约旱念I(lǐng)土上堅(jiān)持著自己的信念——我們稱之為“小字庫(kù)技術(shù)”。甚至有些人堅(jiān)持使用圖片記事,那么自然的被視作是“無(wú)字庫(kù)技術(shù)”。
世界在前進(jìn),即便后來(lái)世界技術(shù)的格局發(fā)生了怎樣的變化,即便一些曾經(jīng)約定的不合理的東西也會(huì)作為最底層的協(xié)議支持者新世界,就像是烏龜駝著的世界。任何觸動(dòng)這些底層的行為都會(huì)受到世界的背叛,所以,拋棄情感上的東西,我們來(lái)研究一下ACSII的構(gòu)成原理和實(shí)現(xiàn)方法。
對(duì)不起大家,我寫這些東西的目的就是面向初學(xué)者。事實(shí)上,如各位所說(shuō),我并非高手,所以很多地方漏出了類似“內(nèi)存映射”之類的馬腳。這里我只想做一點(diǎn)解釋,只有我弄懂了的東西,我才能用通俗的方法和大家解釋,我一竅不通的東西就只好原樣照搬打腫臉充胖子了。呵呵。還請(qǐng)?jiān)彙J聦?shí)上,就拿“內(nèi)存映射”這個(gè)問(wèn)題來(lái)說(shuō),我使用的大段大段的文字來(lái)解釋這個(gè)概念,因?yàn)榧幢闶橇_嗦,我也最多只能用“屏幕的一塊區(qū)域?qū)?yīng)內(nèi)存的一塊區(qū)域”這樣仍然抽象的話語(yǔ)來(lái)解釋,反而顯得我騙稿費(fèi)一般,所以不如先提出一個(gè)名詞,把解釋溶化在后面的文字中。
本來(lái),開(kāi)篇就說(shuō)得很清楚,我寫這些東西的目的不是等大家來(lái)喊牛,姑妄言之,姑妄聽(tīng)之,水平有限,沒(méi)有刻意去追求什么文本格式上的東西,自然可能不對(duì)大家胃口,我以后注意就是了。但是,說(shuō)回來(lái),寫這些東西的心情和大家寫伯克的時(shí)候差不多,多半是吐吐心中不吐不快的東西罷了,所以,由著性子,演繹也罷,說(shuō)明書(shū)也罷,文檔整理稿也罷,那要看那一陣子我正在看什么書(shū)了,如果哪天我不幸開(kāi)始看小說(shuō),來(lái)一個(gè)欲知后事請(qǐng)聽(tīng)下回分解也說(shuō)不定。
我的專業(yè)本來(lái)就是軟件工程,所以寫出這些文字,非常自然。
1 ASCII字符集
ASCII(American Standard Code forInformation InterChange)——美國(guó)通用信息交換編碼。他是現(xiàn)在流行的眾多編碼的榜樣,雖然使用僅僅7位二進(jìn)制表示(通常用一個(gè)字節(jié)表示),但是卻是眾多編碼系統(tǒng)的基礎(chǔ),比方說(shuō)16位二進(jìn)制為組成的Unicode編碼,證據(jù)就是,只要在ASCII碼前面加9個(gè)零就成完成了轉(zhuǎn)換。當(dāng)然,仍然有不聽(tīng)話的,比方說(shuō)IBM老大的EBCDIC碼(大型計(jì)算機(jī)系統(tǒng)上用的)。
大家都注意到了7位二進(jìn)制表示的編碼顯然只能有128個(gè)字符的容量,那么,用一個(gè)字節(jié)256個(gè)字符的容量豈不是造成了浪費(fèi)?于是,現(xiàn)在PC機(jī)上普遍通用的IBM擴(kuò)展ASCII碼從128~255開(kāi)始擴(kuò)展了128個(gè)字符——注意,這128個(gè)字符并不是通用的,即便在我們能接觸的大部分場(chǎng)合他們都有效,但是記住他們的“非常任理事國(guó)”的身份是擁有重大意義的。
比方說(shuō),我們的顯示系統(tǒng)只需要顯示E文字母和數(shù)字還有一些標(biāo)點(diǎn)符號(hào),那么,干什么要這些無(wú)用的字符充數(shù)呢?要知道,一個(gè)字母存儲(chǔ)起來(lái)需要至少8*7的點(diǎn)陣(7個(gè)字節(jié))??!事實(shí)上,由于幾乎所有通用單片機(jī)內(nèi)部都不帶有ASCII字庫(kù)(字模碼),所以,我們必須把他們存儲(chǔ)起來(lái),并且還不能打破原有的存儲(chǔ)模式,不然通過(guò)ASCII碼作為索引我們就找不到他們了。為了完成對(duì)字模庫(kù)的簡(jiǎn)化,我們需要知道他們的構(gòu)成方式,然后再考慮如何去獲取一個(gè)已知的標(biāo)準(zhǔn)字模庫(kù),并按照我們?cè)O(shè)計(jì)的方法去簡(jiǎn)化他……可憐的AVR,存儲(chǔ)器又要吃緊了。
從古老的教科書(shū)上,很容易獲得一張ASCII編碼表。因?yàn)榇蠹叶际歉鉋mbedded System開(kāi)發(fā)的(為了顯示大家工作的高深程度,請(qǐng)?jiān)试S我掉書(shū)袋),所以,這里我更多的要講述一下ASCII編碼一些不太被人注意的特性,一些只有從二進(jìn)制角度才容易看出的特性。
1)ASCII碼由7位二進(jìn)制組成;
[6][5][4][3][2][1][0]
2)[6:5]為用來(lái)表示ASCII編碼的組分類
控制字符組(顯示不需要顯示的東西)
數(shù)字字符和標(biāo)點(diǎn)符號(hào)組
大寫字符和特殊字符
小寫字符和特殊字符
3)只要把大寫字母的第6位也就是[5]置位就是現(xiàn)了到小寫字母的轉(zhuǎn)換,反之亦然;
4)數(shù)字的ASCII碼[3:0]位的值與它要表示的數(shù)值相同;
例如:
“0” 0x30
“1”0x31
依照上面的編碼規(guī)則,ASCII碼的字模碼文件存儲(chǔ)的方式為:
char c;
……
fAddress = c* 8 * 16;//超級(jí)簡(jiǎn)單哈,這是計(jì)算機(jī)系統(tǒng)上標(biāo)準(zhǔn)8*16的ASCII字符集
fAddress = c* 8 * 8; //這是計(jì)算機(jī)系統(tǒng)使用的8*8小字符集
聰明的大家已經(jīng)知道如何在存儲(chǔ)器中獲得字模碼了吧?
就是訪問(wèn)存儲(chǔ)的“基地址+fAddress”就可以了。
為了便于后面大家實(shí)現(xiàn)漢字顯示時(shí)候的代碼移植(回避全角和半角問(wèn)題),我們使用8*16的大字符集,至于你想使用小字符集,那么就看你的愛(ài)好了。
2 How toget them?
這里我們來(lái)順手說(shuō)說(shuō)字模碼獲得的問(wèn)題。
不可否認(rèn),現(xiàn)在網(wǎng)上很多兄弟寫的字模制作軟件水平之高,已經(jīng)到了令人嘆為觀止的地步,只可惜當(dāng)時(shí)我學(xué)習(xí)字庫(kù)問(wèn)題的時(shí)候,尚且沒(méi)有解決溫飽,更不用說(shuō)上網(wǎng)了。而且,這些字模軟件無(wú)不在客觀上支持了字模的“無(wú)政府主義”,小字庫(kù)和無(wú)字庫(kù)技術(shù)在一些不恰當(dāng)?shù)膱?chǎng)合也被大量濫用,嚴(yán)重影響了接著寫你代碼同志的心情……鬼知道原來(lái)跳槽的家伙如何定義那該死的字庫(kù)的,所以,提倡在何時(shí)的場(chǎng)合使用標(biāo)準(zhǔn)的字模庫(kù)還是非常有必要的。
首先說(shuō)說(shuō)一種簡(jiǎn)單的獲取字模的方法。
不知道還有多少人記得UCDOS,中國(guó)漢字操作系統(tǒng)的“希望”。金山WPS,CCED……TX.com,這些東西讓人難忘啊。我們的字模庫(kù)很容易從這樣具有我國(guó)獨(dú)立知識(shí)產(chǎn)權(quán)的系統(tǒng)中獲得。所有的東西都放在
UCDOS
目錄下面。我們選取這次需要的文件“ASC16”。順手說(shuō)下,漢字庫(kù)也可以從里面獲得“HZK16”。其他的字模庫(kù)在
UCDOSFNT
目錄下面。
還有一種BT的方法可以獲得8*8的字庫(kù)。大家記得BIOS吧……呵呵,利用TC寫一個(gè)中斷程序,直接讀出來(lái)……哈哈。后面有機(jī)會(huì)我會(huì)附上代碼,如果我能記得地址的話。
3 字庫(kù)減肥
查看一下Mega8的Datasheet,上面赫然寫著8K Flash,再看看ASC16的大小4K,我不知道有多少人不會(huì)打寒顫。更不用說(shuō)260多K的漢字庫(kù)了,看來(lái)要么外擴(kuò)存儲(chǔ)器,要么只能選擇西文顯示,并且對(duì)ASC16庫(kù)進(jìn)行減肥。
其實(shí),減肥并不是一個(gè)可以稱之為技術(shù)的行為,總原則就是丟棄無(wú)用的部分,同時(shí)修改索引方式以保證外界使用減肥前方文字魔窟文件的索引方式不至于出錯(cuò)就可以了。就拿ASC16的減肥工作來(lái)說(shuō)吧,很顯然,我們并不需要擴(kuò)展字符128~255的那個(gè)部分,可以減小大小為16*128 = 2K的大小,再加上基本字符基的四個(gè)區(qū)中,控制字符區(qū)顯然也是可以舍棄的,所以,還可以減少16*32 = 512B的大小,也就是說(shuō),剩下的文件只有1.5K大小了,哈哈,總算可以接受了。當(dāng)然如果你選擇了8*8的字模,就更小了。
以上完成的只是第一步,借助類似UltraEdit這樣的編輯工具都可以做到,然后我們?cè)侔炎帜?kù)寫成數(shù)組的形式,比方說(shuō):
const charASC_Lib[][16] = {
……
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
……
}
包含入頭文件,就可以了。
下面我們需要一個(gè)訪問(wèn)函數(shù),用來(lái)安全的有效的訪問(wèn)到我們需要的字模庫(kù):
char*getASCLIB(char ASC)
{
if ((ASC <32 )|| (ASC > 127))
{
returnASC_Lib[CharStringNULL]; //需要一個(gè)空字符串作為安全返回
}
returnASC_Lib[ASC];
}
配合12864頭文件中公版中都有的那個(gè)顯示圖片的函數(shù),就可以顯示字符了。例如:
voidDispBITMap(const char *String,char StringLength,char X,char Y,char DispModel);
我們還可以再對(duì)這個(gè)函數(shù)包裝一下,實(shí)現(xiàn)16 * 4的文本模式。使用CLocate(x,y)來(lái)定位字符,用Print("")來(lái)顯示字符串,用PrintN()來(lái)顯示數(shù)字……哈哈。這一部分就留給大家自己來(lái)做了,不過(guò)是幾個(gè)函數(shù)加宏定義罷了,相信自己簡(jiǎn)單的。
至于如何實(shí)現(xiàn)任意位置顯示字符,還有一些字符特效的實(shí)現(xiàn),在下一節(jié)里面具體說(shuō)明。
這是我寫的函數(shù)
/********************************************************
* 函數(shù)說(shuō)明:讀取顯示數(shù)據(jù)指令 *
* 輸出: 顯示數(shù)據(jù) *
********************************************************/
chargetLCD12864Data(void)
{
char TempData= 0;
char a = 0;
LCD12864_SetModel_Data;
LCD12864_SetModel_Read;
LCD12864_SetEnable;
LCD12864_SetDisable;
LCD12864_SetEnable;
asm("nop");
TempData =ReadDataPORT;
評(píng)論