1. 程式人生 > >嵌入式裝置LCD模組漢字型檔檔案生成方式

嵌入式裝置LCD模組漢字型檔檔案生成方式

近期有專案需要用的LCD顯示沐足顯示一些中文,對比了下帶字型檔的模組要比不帶字型檔的模組要貴得多,想想那就自己建立字型檔吧,能剩下不少費用,再說裝置內部的FLASH大把的容量,不利用也有點浪費了。


下文轉載自:http://www.rationmcu.com/elecjc/356.html

學完這篇文章,你將會使你的微控制器顯示系統中加入中文顯示的功能。

1.導言

和微控制器搭配的顯示器,有12864、TFT、OLED等。在有些系統中,我們需要顯示漢字,可以購買漢字晶片,或者購買帶漢字顯示的顯示器,當然,也可以自己做字型檔。

這裡我們介紹一種自己做字型檔的方法,成本2元人民幣左右。

2.漢字顯示原理

看原理需要知道什麼是畫素:畫素是液晶屏的最小單位,看你的手機螢幕或者電腦螢幕,他們實際上是由一個一個的正方形組成的,如果你的電腦或手機螢幕解析度太高,不容易看到,需要藉助放大鏡,解析度低的話,仔細一看就看見了,都是由一個一個的正方形組成的,這裡面的一個正方形,就是1個畫素。例如,12864螢幕就是128畫素*64畫素的螢幕,即橫著有12864個正方形,豎著有64個正方形。

12864放大

上圖是12864螢幕的一角,請你仔細看看,是不是一個一個的正方形組成?

比128*64大的解析度是320*240,還有800*600,1024*768,1280*720等,總之,解析度越大,人的肉眼就越但不見它是由一個一個小正方形組成的。所以現在的手機螢幕是越來越高,當你用慣一個解析度極高的手機,再去用你原來解析度極低的手機,你就會發現原來的那個手機真是很模糊!

講完了畫素的概念,下面開始講漢字顯示的原理:

現在流行的漢字字型檔有兩種,一種是GB2312、一種是GBK。這是兩種不同的編碼約定。

  • GB2312有六千多個漢字,是一些常用的漢字
  • GBK有2萬多個漢字,包含所有的GB2312漢字,包含整個中國的漢字

假如我們想在液晶顯示器上顯示一個16*16畫素大小的漢字“瑞”,怎麼辦呢?先看一下“瑞”字在液晶顯示器上被放大的效果:

瑞

上面的這個瑞即是16*16畫素大小的字型,你可以數一下上面的畫素點。你可以看一下,在上面“亮”的地方用“寫點函式”寫成和其它點不同的顏色,不就可以了嗎!按照這個思想,我們就需要採用一種有效的辦法了。從上面影象的右上角開始掃描,每行有16個點,即可以用兩個位元組來表示,“暗”的地方用0表示,亮的地方用1表示,那麼第一行就可以寫成十六進位制的00 20,以此類推,可以得出第二行,第三行的位元組碼,如此一來,一個漢字就需要32個位元組來表示。搞好了漢字的這些碼,在程式中給TFT開個16*16大小的區域,然後開始掃描這些位元組,遇到0,寫背景色,遇到1,寫定義的顏色。漢字顯示就是如此了。

3.為什麼顯示英文一般不用字型檔晶片?

英文的單詞都是由26個字母構成了,加上大小寫的區別和一些字元,也不過才95個。假如要顯示8*16畫素大小的字元,每一個字元需要16個位元組的字型檔空間,95個字元即是95*16=570個位元組。即佔用570個位元組的RAM。對於LPC1114的8K位元組RAM來說,搓搓有餘了。

4.為什麼顯示中文需要字型檔晶片?

顯示中文的話,必須需要每一個字的字模,16*16畫素大小的中文,每一箇中文都要32個位元組。GBK收錄了中文兩萬多個,如果要都能顯示,需要700多K位元組的空間。

所以,我們選擇了把這些字型檔放在外部儲存器當中,我們選擇了2M的FLASH儲存晶片W25Q16做為儲存媒介。放個700多K的字型檔足夠了,如果你願意,同時放兩種字型的字型檔都沒問題。

5.如何把GBK字型檔做成字模?(此部分做字模參考阿莫論壇一帖子,非瑞生原創,特此感謝分享者)

5.1需要準備的檔案和軟體

  • 取模軟體
  • GBK字型檔
  • 二進位制檔案生成工具

點此下載:GBK字型檔製作軟體和檔案

5.2開始製作

取模軟體

在工具欄處點“開啟”按鈕,開啟gbk_ziku.txt檔案,然後根據自己的需要,設定想要的取模方式,然後點工具欄上的“輸出”按鈕 並等待其完成,完成後會在取模軟體所在路徑生成了一個temp.txt檔案,修改這個檔名,比如現在我是按照“宋體、點陣數為16、字重為4、取模為為16*16、對齊設定為左上、方向設定為橫向取模,高位在左”的方式來取的字模,也就是我平時TFT常用的一種字模,改檔名為st16x16.txt 。

為了生成的方便,我們在D盤根目錄下新建一個資料夾,名稱就叫ziku吧,然後,把ziku.exe 和 st16x16.txt複製一份到這個資料夾裡。

開啟自己計算機的命令視窗:“開始”->“執行”->“cmd”,如下圖所示:

命令1

然後用cd命令進入到我們剛剛建的ziku資料夾下,輸入命令如下圖所示:

命令2

輸入命令,生成字型檔檔案,如下圖所示:

命令3

回車,然後程式會在ziku資料夾下生成一個名稱固定為ziku.bin的字型檔檔案

命令4

為了區分,把這個字型檔檔案修改名稱為st16x16.bin 。

到此,字型檔已經制作完成。

6.如何把做好的GBK字型檔字模儲存到W25Q16中?

硬體:電腦串列埠—微控制器—W25Q16

程式:微控制器與電腦採用串列埠連線,微控制器與W25Q16採用SPI方式連線。所以,我們只需要給微控制器寫一個接收串列埠資料再把資料通過SPI口傳輸到W25Q16中的程式即可。

下面的視訊是瑞生LPC1114開發板下載GBK字型檔的演示:(支援超清模式觀看)

7.微控制器如何讀取W25Q16中的字模並顯示在液晶屏上?

假設我們的GBK字模是從W25Q16地址中的0x100開始儲存的,那麼,從0x100地址開始,微控制器讀取32個位元組,就是GBK字型檔的第一個字“丂”的字模,再讀32個位元組,就是GBK字型檔第二個字“丄”的字模。(有人會問,你是怎麼知道GBK字型檔第幾個字是什麼的?答:你把上文中5.1節提到的檔案下載後,開啟GBK字型檔,就看見了。)根據上文中第2步講的原理,字模中,遇到0就給LCD的1個畫素畫一個顏色,遇到1就給LCD的下一個畫素畫不同的顏色,把32個位元組都捋一遍,一個漢字就顯示在LCD上了。

如果我們想要顯示漢字“瑞”,我們該從W25Q16中的哪個位元組開始提取它的字模呢?這時候,就需要知道字元儲存編碼的原理了。

字元編碼原理:英文字母帶各種符號等共有95個,都有自己的ascii碼,一個字母或者符號就是一個ascii碼。漢字以及漢字的符號是需要2個位元組來儲存,在keil等主流編譯器中,一般都是以GBK編碼方式儲存。

GBK編碼:每個GBK碼由2個位元組組成,第一個位元組為0X81~0XFE,第二個位元組分為兩部分,一是0X40~0X7E,二是0X80~0XFE。例如漢字“瑞”的GBK編碼為C8 F0,第一位元組C8,位於0X81~0XFE之間,第二位元組F0,位於0X40~0XFE之間。第一個位元組代表的意義稱為區,那麼GBK裡面總共有126個區(0XFE-0X81+1=126);第二個位元組代表的意義就是每個區內有多少個漢字,算了一下,一共有190個(0XFE-0X80+0X7E-0X40+2=190)。那麼,GBK一共儲存了126X190=23940個漢字。

我們仔細看GBK編碼第二個位元組兩部分,0X40~0X7E 0X80~0XFE,也就是說它是從0X40~到0XFF,中間的0x7F和最後的0xFF沒有用到。但是為了能夠線性查詢,我們暫且認為這兩個位元組也存在,就是我們強制把每個區190個漢字當做每個區192個漢字,不過0X7F和0XFF上沒有漢字。

定義GBKH代表第一個位元組,GBKL代表第二個位元組,字型檔的偏移量offset,放入W25Q16的字型檔從0x100地址開始儲存,那麼獲取某個漢字的字模的函式就可以寫成:

void Get_GBK_DZK(uint8_t *code, uint8_t *dz_data)
{
    uint8_t GBKH,GBKL;                 
    uint32_t offset;        

    GBKH=*code;
    GBKL=*(code+1);     
    if(GBKH>0XFE||GBKH<0X81)return;
    GBKH-=0x81;
    GBKL-=0x40;
    offset=((uint32_t)192*GBKH+GBKL)*32;
    W25Q16_Read(dz_data,offset+0x100,32);           
    return;
}

函式中,引數*code帶入漢字的兩位元組編碼,*dz_data是一個32個位元組的資料,帶入函式中,就可以得到任何一個漢字的字模了。例如:

    uint8_t buf[32];
    Get_GBK_DZK("瑞", buf);