使用Windows中的字體生成點陣字庫

所有的漢字或者英文都是下面的原理,
由左至右,每8個點佔用一個字節,最後不足8個字節的佔用一個字節,而且從最高位向最低位排列。
生成的字庫說明:(以12×12例子)


一個漢字佔用字節數:12÷8=1····4也就是佔用了2×12=24個字節。
編碼排序A0A0→A0FE A1A0→A2FE依次排列。
以12×12字庫的“我”爲例:“我”的編碼爲CED2,所以在漢字排在CEH-AOH=2EH區的D2H-A0H=32H個。所以在12×12字庫的起始位置就是[{FE-A0}*2EH+32H]*24=104976開始的24個字節就是我的點陣模。
其他的類推即可。
英文點陣也是如此推理。

在DOS程序中使用點陣字庫的方法

回到頂部

    首先需要理解的是點陣字庫是一個數據文件,在這個數據文件裏面保存了所有文字的點陣數據.至於什麼是點陣,我想我不講大家都知道 的,使用過"文曲星"之類的電子辭典吧,那個的液晶顯示器上面顯示的漢子就能夠明顯的看出"點陣"的痕跡.在 PC 機上也是如此,文字也是由點陣來組成了,不同的是,PC機顯示器的顯示分辨率更高,高到了我們肉眼無法區分的地步,因此"點陣"的痕跡也就不那麼明顯了.

    點陣、矩陣、位圖這三個概念在本質上是有聯繫的,從某種程度上來講,這三個就是同義詞.點陣從本質上講就是單色位圖,他使用一個比特來表示一個點,如果這 個比特爲0,表示某個位置沒有點,如果爲1表示某個位置有點.矩陣和位圖有着密不可分的聯繫,矩陣其實是位圖的數學抽象,是一個二維的陣列.位圖就是這種 二維的陣列,這個陣列中的 (x,y) 位置上的數據代表的就是對原始圖形進行採樣量化後的顏色值.但是,另一方面,我們要面對的問題是,計算機中數據的存放都是一維的,線性的.因此,我們需要 將二維的數據線性化到一維裏面去.通常的做法就是將二維數據按行順序的存放,這樣就線性化到了一維.

    那麼點陣字的數據存放細節到底是怎麼樣的呢.其實也十分的簡單,舉個例子最能說明問題.比如說 16*16 的點陣,也就是說每一行有16個點,由於一個點使用一個比特來表示,如果這個比特的值爲1,則表示這個位置有點,如果這個比特的值爲0,則表示這個位置沒 有點,那麼一行也就需要16個比特,而8個比特就是一個字節,也就是說,這個點陣中,一行的數據需要兩個字節來存放.第一行的前八個點的數據存放在點陣數 據的第一個字節裏面,第一行的後面八個點的數據存放在點陣數據的第二個字節裏面,第二行的前八個點的數據存放在點陣數據的第三個字節裏面,…,然後後 面的就以此類推了.這樣我們可以計算出存放一個點陣總共需要32個字節.看看下面這個圖形化的例子:

    | |1| | | | | | | | | | |1| | | |

    | | |1|1| |1|1|1|1|1|1|1|1|1| | |

    | | | |1| | | | | | | | |1| | | |

    |1| | | | | |1| | | | | |1| | | |

    | |1|1| | | |1| | | | | |1| | | |

    | | |1| | | |1| | | | |1| | | | |

    | | | | |1| | |1| | | |1| | | | |

    | | | |1| | | |1| | |1| | | | | |

    | | |1| | | | | |1| |1| | | | | |

    |1|1|1| | | | | | |1| | | | | | |

    | | |1| | | | | |1| |1| | | | | |

    | | |1| | | | |1| | | |1| | | | |

    | | |1| | | |1| | | | | |1| | | |

    | | |1| | |1| | | | | | |1|1|1| |

    | | | | |1| | | | | | | | |1| | |

    | | | | | | | | | | | | | | | | |

    可以看出這是一個"漢"字的點陣,當然文本的方式效果不是很好.根據上面的原則,我們可以寫出這個點陣的點陣數 據:0x40,0x08,0x37,0xfc,0x10,0x08,…, 當然寫這個確實很麻煩所以我不再繼續下去.我這樣做,也只是爲了向你說明,在點陣字庫中,每一個點陣的數據就是按照這種方式存放的.

    當然也存在着不規則的點陣,這裏說的不規則,指的是點陣的寬度不是8的倍數,比如 12*12 的點陣,那麼這樣的點陣數據又是如何存放的呢?其實也很簡單,每一行的前面8個點存放在一個字節裏面,每一行的剩下的4點就使用一個字節來存放,也就是說 剩下的4個點將佔用一個字節的高4位,而這個字節的低4位沒有使用,全部都默認的爲零.這樣做當然顯得有點浪費,不過卻能夠便於我們進行存放和尋址.對於 其他不規則的點陣,也是按照這個原則進行處理的.這樣我們可以得出一個 m*n 的點陣所佔用的字節數爲 (m+7)/8*n.

    在明白了以上所講的以後,我們可以寫出一個顯示一個任意大小的點陣字模的函數,這個函數的功能是輸出一個寬度爲w,高度爲h的字模到屏幕的 (x,y) 座標出,文字的顏色爲 color,文字的點陣數據爲 pdata 所指:

    /*輸出字模的函數*/

    void _draw_model(char *pdata, int w, int h, int x, int y, int color)

    {

    int     i;    /* 控制行 */

    int     j;    /* 控制一行中的8個點 */

    int     k;    /* 一行中的第幾個"8個點"了 */

    int     nc;   /* 到點陣數據的第幾個字節了 */

    int     cols; /* 控制列 */

    BYTE    static mask[8]={128, 64, 32, 16, 8, 4, 2, 1}; /* 位屏蔽字 */

    w = (w + 7) / 8 * 8; /* 重新計算w */

    nc = 0;

    for (i=0; i<h; i++)

    {

    cols = 0;

    for (k=0; k<w/8; k++)

    {

    for (j=0; j<8; j++)

    {

    if (pdata[nc]&mask[j])

    putpixel(x+cols, y+i, color);

    cols++;

    }

    nc++;

    }

    }

    }

    代碼很簡單,不用怎麼講解就能看懂,代碼可能不是最優化的,但是應該是最易讀懂的.其中的 putpixel 函數,使用的是TC提供的 Graphics 中的畫點函數.使用這個函數就可以完成點陣任意大小的點陣字模的輸出.

    接下來的問題就是如何在漢子庫中尋址某個漢子的點陣數據了.要解決這個問題,首先需要了解漢字在計算機中是如何表示的.在計算機中英文可以使用 ASCII 碼來表示,而漢字使用的是擴展 ASCII 碼,並且使用兩個擴展 ASCII 碼來表示一個漢字.一個 ASCII 碼使用一個字節表示,所謂擴展 ASCII 碼,也就是 ASCII 碼的最高位是1的 ASCII 碼,簡單的說就是碼值大於等於 128 的 ASCII 碼.一個漢字由兩個擴展 ASCII 碼組成,第一個擴展 ASCII 碼用來存放區碼,第二個擴展 ASCII 碼用來存放位碼.在 GB2312-80 標準中,將所有的漢字分爲94個區,每個區有94個位可以存放94個漢字,形成了人們常說的區位碼,這樣總共就有 94*94=8836 個漢字.在點陣字庫中,漢字點陣數據就是按照這個區位的順序來存放的,也就是最先存放的是第一個區的漢字點陣數據,在每一個區中有是按照位的順序來存放 的.在漢字的內碼中,漢字區位碼的存放實在擴展 ASCII 基礎上存放的,並且將區碼和位碼都加上了32,然後存放在兩個擴展 ASCII 碼中.具體的說就是:

    第一個擴展ASCII碼 = 128+32 + 漢字區碼

    第二個擴展ASCII嗎 = 128+32 + 漢字位碼

    如果用char hz[2]來表示一個漢字,那麼我可以計算出這個漢字的區位碼爲:

    區碼 = hz[0] - 128 - 32 = hz[0] - 160

    位碼 = hz[1] - 128 - 32 = hz[1] - 160.

    這樣,我們可以根據區位碼在文件中進行殉職了,尋址公式如下:

    漢字點陣數據在字庫文件中的偏移 = ((區碼-1) * 94 + 位碼) * 一個點陣字模佔用的字節數

    在尋址以後,即可讀取漢字的點陣數據到緩衝區進行顯示了.以下是實現代碼:

    /* 輸出一個漢字的函數 */

    void _draw_hz(char hz[2], FILE *fp, int x, int y, int w, int h, int color)

    {

    char fONtbuf[128];   /* 足夠大的緩衝區,也可以動態分配 */

    int ch0 = (BYTE)hz[0]-0xA0; /* 區碼 */

    int ch1 = (BYTE)hz[1]-0xA0; /* 位碼 */

    /* 計算偏移 */

    long offset = (long)pf->_hz_buf_size * ((ch0 - 1) * 94 + ch1 - 1);

    fseek(fp, offset, SEEK_SET);              /* 進行尋址 */

    fread(fontbuf, 1, (w + 7) / 8 * h, fp);   /* 讀入點陣數據 */

    _draw_model(fontbuf, w, h, x, y, color); /* 繪製字模 */

    }

    以上介紹完了中文點陣字庫的原理,當然還有英文點陣字庫了.英文點陣字庫中單個點陣字模數據的存放方式與中文是一模一樣的,也就是對我們所寫的 _draw_model 函數同樣可以使用到英文字庫中.唯一不同的是對點陣字庫的尋址上.英文使用的就是 ASCII 碼,其碼值是0到127,尋址公式爲:

    英文點陣數據在英文點陣字庫中的偏移 = 英文的ASCII碼 * 一個英文字模佔用的字節數

    可以看到,區分中英文的關鍵就是,一個字符是 ASCII 碼還是擴展 ASCII 碼,如果是 ASCII 碼,其範圍是0到127,這樣是使用的英文字庫,如果是擴展 ASCII 碼,則與其後的另一個擴展 ASCII 碼組成漢字內碼,使用中文字庫進行顯示.只要正確區分 ASCII 碼的類型並進行分別的處理,也就能實現中英文字符串的混合輸出了.

點陣字庫和矢量字庫的差別

回到頂部

    我們都只知道,各種字符在電腦屏幕上都是以一些點來表示的,因此也叫點陣.最早的字庫就是直接把這些點存儲起來,就是點陣字庫.常見的漢字點陣字庫有 16x16, 24x24 等.點陣字庫也有很多種,主要區別在於其中存儲編碼的方式不同.點陣字庫的最大缺點就是它是固定分辨率的,也就是每種字庫都有固定的大小尺寸,在原始尺寸下使用,效果很好,但如果將其放大或縮小使用,效果就很糟糕了,就會出現我們通常說的鋸齒現象.因爲需要的字體大小組合有無數種,我們也不可能爲每種大小都定義一個點陣字庫.於是就出現了矢量字庫.

    矢量字庫

    矢量字庫是把每個字符的筆劃分解成各種直線和曲線,然後記下這些直線和曲線的參數,在顯示的時候,再根據具體的尺寸大小,畫出這些線條,就還原了原來的字符.它的好處就是可以隨意放大縮小而不失真.而且所需存儲量和字符大小無關.矢量字庫有很多種,區別在於他們採用的不同數學模型來描述組成字符的線條.常見的矢量字庫有 Type1字庫和Truetype字庫.

    在點陣字庫中,每個字符由一個位圖表示(如圖2.5所示),並把它用一個稱爲字符掩膜的矩陣來表示,其中的每個元素都是一位二進制數,如果該位爲1表示字符的筆畫經過此位,該像素置爲字符顏色;如果該位爲0,表示字符的筆畫不經過此位,該像素置爲背景顏色.點陣字符的顯示分爲兩步:首先從字庫中將它的位圖檢索出來,然後將檢索到的位圖寫到幀緩衝器中.

    在實際應用中,同一個字符有多種字體(如宋體、楷體等),每種字體又有多種大小型號,因此字庫的存儲空間十分龐大.爲了減少存儲空間,一般採用壓縮技術.

    矢量字符記錄字符的筆畫信息而不是整個位圖,具有存儲空間小,美觀、變換方便等優點.例如:在AutoCAD中使用圖形實體-形(Shape)-來定義矢量字符,其中,採用了直線和圓弧作爲基本的筆畫來對矢量字符進行描述. 對於字符的旋轉、放大、縮小等幾何變換,點陣字符需要對其位圖中的每個象素進行變換,而矢量字符則只需要對其幾何圖素進行變換就可以了,例如:對直線筆畫的兩個端點進行變換,對圓弧的起點、終點、半徑和圓心進行變換等等.

    矢量字符的顯示也分爲兩步.首先從字庫中將它的字符信息.然後取出端點座標,對其進行適當的幾何變換,再根據各端點的標誌顯示出字符.

    輪廓字形法是當今國際上最流行的一種字符表示方法,其壓縮比大,且能保證字符質量.輪廓字形法採用直線、B樣條/Bezier曲線的集合來描述一個字符的輪廓線.輪廓線構成一個或若干個封閉的平面區域.輪廓線定義加上一些指示橫寬、豎寬、基點、基線等等控制信息就構成了字符的壓縮數據.

如何使用Windows的系統字庫生成點陣字庫?

回到頂部

    我的程序現在只能預覽一個漢字的不同字體的點陣表達.

    界面很簡單:   一個輸出點陣大小的選擇列表(8x8,16x16,24x24等),一個系統中已有的字體名稱列表,一個預覽按鈕,一塊畫圖顯示區域.

    得到字體列表的方法:(作者稱這一段是用來取回系統的字體,然後添加到下拉框中)

    //取字體名稱列表的回調函數,使用前要聲明一下該方法

    int   CALLBACK   MyEnumFONtProc(ENUMLOGFONTEX*   lpelf,NEWTEXTMETRICEX*   lpntm,DWORD   nFontType,long   lParam)

    {

    CFontPeekerDlg*   pWnd=(CFontPeekerDlg*)   lParam;

    if(pWnd)

    {

    if(   pWnd->m_combo_sfont.FindSTring(0,   lpelf->elfLogFont.lfFaceName)   <0   )

    pWnd->m_combo_sfont.AddString(lpelf->elfLogFont.lfFaceName);

    return   1;

    }

    return   0;

    }

    //說明:CFontPeekerDlg   是我的dialog的類名,   m_combo_sfont是列表名稱下拉combobox關聯的control變量

    //調用的地方     (******問題1:下面那個&lf怎麼得到呢……)

    {

    ::EnumFontFamiliesEx((HDC)   dc,&lf,   (FONTENUMPROC)MyEnumFontProc,(LPARAM)   this,0);

    m_combo_sfont.SetCurSel(0);

    }

    字體預覽:

    如果點陣大小選擇16,顯示的時候就畫出16x16個方格.自定義一個類CMyStatic繼承自CStatic,用來畫圖.在CMyStatic的OnPaint()函數中計算並顯示.

    取得字體:

    常用的方法:用CreateFont創建字體,把字TextOut再用GetPixel()取點存入數組.   缺點:必須把字TextOut出來,能在屏幕上看見,不爽.

    我的方法,用這個函數:GetGlyphOutline(),可以得到一個字的輪廓矢量或者位圖.可以不用textout到屏幕,直接取得字模信息

    函數原型如下:

    DWORD   GetGlyphOutline(

    HDC   hdc,                     //畫圖設備句柄

    UINT   uChar,                 //將要讀取的字符/漢字

    UINT   uFormat,             //返回數據的格式(字的外形輪廓還是字的位圖)

    LPGLYPHMETRICS   lpgm,     //   GLYPHMETRICS結構地址,輸出參數

    DWORD   cbBuffer,       //輸出數據緩衝區的大小

    LPVOID   lpvBuffer,     //輸出數據緩衝區的地址

    CONST   MAT2   *lpmat2   //轉置矩陣的地址

    );

    說明:

    uChar字符需要判斷是否是漢字還是英文字符.中文佔2個字節長度.

    lpgm是輸出函數,調用GetGlyphOutline()是無須給lpgm   賦值.

    lpmat2如果不需要轉置,將   eM11.value=1;   eM22.value=1;   即可.

    cbBuffer緩衝區的大小,可以先通過調用GetGlyphOutline(……lpgm,   0,   NULL,   mat);   來取得,然後動態分配lpvBuffer,再一次調用GetGlyphOutline,將信息存到lpvBuffer.   使用完畢後再釋放lpvBuffer.

    程序示例:(***問題2:用這段程序,我獲取的字符點陣總都是一樣的,不管什麼字……)

    ……前面部分省略……

    GLYPHMETRICS   glyph;

    MAT2   m2;

    memset(&m2,   0,   sizeof(MAT2));

    m2.eM11.value   =   1;

    m2.eM22.value   =   1;

    //取得buffer的大小

    DWORD   cbBuf   =   dc.GetGlyphOutline(   nChar,   GGO_BITMAP,   &glyph,   0L,   NULL,   &m2);

    BYTE*   pBuf=NULL;

    //返回GDI_ERROR表示失敗.

    if(   cbBuf   !=   GDI_ERROR   )

    {

    pBuf   =   new   BYTE[cbBuf];

    //輸出位圖GGO_BITMAP   的信息.輸出信息4字節(DWORD)對齊

    dc.GetGlyphOutline(   nChar,   GGO_BITMAP,   &glyph,   cbBuf,   pBuf,   &m2);

    }

    else

    {

    if(m_pFont!=NULL)

    delete   m_pFont;

    return;

    }

    編程中遇到問題:

    一開始,GetGlyphOutline總是返回-1,getLastError顯示是"無法完成的功能",後來發現是因爲調用之前沒有給hdc設置Font.

    後來能取得pBuf信息後,又開始鬱悶,因爲不太明白bitmap的結果是按什麼排列的.後來跟蹤漢字"一"來調試(這個字簡單),注意到了glyph.gmBlackBoxX   其實就是輸出位圖的寬度,glyph.gmBlackBoxY就是高度.如果gmBlackBoxX=15,glyph.gmBlackBoxY=2,表示輸出的pBuf中有這些信息:位圖有2行信息,每一行使用15   bit來存儲信息.

    例如:我讀取"一":glyph.gmBlackBoxX   =   0x0e,glyph.gmBlackBoxY=0x2;     pBuf長度cbBuf=8   字節

    pBuf信息:       00   08   00   00   ff   fc   00   00

    字符寬度   0x0e=14     則   第一行信息爲:           0000   0000   0000   100       (只取到前14位)

    第二行根據4字節對齊的規則,從0xff開始         1111   1111   1111   110

    看出"一"字了嗎?呵呵

    直到他的存儲之後就可以動手解析輸出的信息了.

    我定義了一個宏#define   BIT(n)     (1<<(n))     用來比較每一個位信息時使用

    後來又遇到了一個問題,就是小頭和大頭的問題了.在我的機器上是little   endian的形式,如果我用

    unsigned   long   *lptr   =   (unsigned   long*)pBuf;

    //j   from   0   to   15

    if(   *lptr   &   BIT(j)   )

    {

    //這時候如果想用j來表示寫1的位數,就錯了

    }

    因爲從字節數組中轉化成unsigned   long型的時候,數值已經經過轉化了,像上例中,實際上是0x0800   在同BIT(j)比較.

    不多說了,比較之前轉化一下就可以了if(   htonl(*lptr)   &   BIT(j)   )

Unicode中文點陣字庫的生成與使用

回到頂部

    點陣字庫包含兩部分信息.首先是點陣字庫文件頭信息,它包含點陣字庫文字的字號、多少位表示一個像素,英文字母與符號的size、起始和結束unicode編碼、在文件中的起始偏移,漢字的size、起始和結束unicode編碼、在文件中的起始偏移.然後是真實的點陣數據,即一段段二進制串,每一串表示一個字母、符號或漢字的點陣信息.

    要生成點陣字庫必須有文字圖形的來源,我的方法是使用ttf字體.ttf字體的顯示採用的是SDL_ttf庫,這是開源圖形庫SDL的一個擴展庫,它使用的是libfreetype以讀取和繪製ttf字體.

    它提供了一個函數,通過傳入一個Unicode編碼便能輸出相應的文字的帶有alpha通道的位圖.那麼我們可以掃描這個位圖以得到相應文字的點陣信息.由於帶有alpha通道,我們可以在點陣信息中也加入權值,使得點陣字庫也有反走樣效果.我採用兩位來表示一個點,這樣會有三級灰度(還有一個表示透明).

    點陣字庫的顯示首先需要將文件頭信息讀取出來,然後根據unicode編碼判斷在哪個區間內,然後用unicode編碼減去此區間的起始unicode編碼,算出相對偏移,並加上此區間的文件起始偏移得到文件的絕對偏移,然後讀出相應位數的數據,最後通過掃描這段二進制串,在屏幕的相應位置輸出點陣字型.

    顯示點陣字體需要頻繁讀取文件,因此最好做一個固定大小的緩存,採用LRU置換算法維護此緩存,以減少磁盤讀取.

標準點陣字庫芯片

回到頂部

標準點陣字庫芯片的特點:

    1.內涵全國信標委授權的標準點陣字型數據、

    2.支持國標字符集GB2312(6,763漢字),GB18030(27,484漢字).

    3.支持多種點陣字型,包括11×12點,15×16點,24×24點,32×32點.

    4.免除了字庫燒錄和測試工序,並節省了2%以上的燒錄損耗.

    5.價格相當於空白FLASH價格

標準點陣字庫芯片的種類和應用

回到頂部

51單片機的13×14點陣縮碼漢卡

回到頂部

    我們歷時數載,開發成"51單片機13×14點陣縮碼漢卡",適用於目前國內外應用最爲廣泛的MCSX-51及其兼容系列單片機.

    與此同時,還開發了13×14點陣漢字字模.13×14點陣字模,可完全與目前通用的16×16點陣漢字字模媲美,其在單片機和嵌入式系統的漢字顯示應用中也具有明顯的經濟價值和實用意義.

    1.單片機目前的漢字顯示

    信息交流的最主要方式之一即文字交流,但由於我國方塊漢字數量繁多,構形迥異,使漢字顯示一直是我國計算機普及的障礙.隨着計算機技術的迅速發展,PC機的漢字顯示已不成問題.但對於成本低、體積小、應用靈活且用量極爲巨大的單片機而言,因其結構簡單,硬件資源十分有限,其漢字顯示仍面對着捉襟見肘,力不從心的窘境.

    目前單片機的漢字顯示有三種基本方法.

    ①採用標準字庫法.即將國標漢字庫固人ROM中,將單片機的硬件和軟件進行特別擴展後以顯示漢字.衆所周知,即使是16×16點陣標準字庫,也須佔用200KB以上的單元內存,而就目前主流5l系列單片機而言,最大尋址範圍僅64KB,即使程序區與數據區合起來也僅128KB內存.因此,若不加特別的擴展設計,不要說檢字程序和用戶空間,僅字庫都裝不下.這種方法雖然可以方便地使用現成標準字庫,但卻需佔用大量的硬件和軟件資源,增加很大一部分成本和設計難度,所以不經常使用.

    ②字模直接固化法.即將所顯示的漢字,依先後順序將其字模一一從標準字庫中提取後,重新固化,予以顯示.此法雖爲簡捷,但只適於顯示少量漢字,且字模的製取繁瑣,軟件的修改維護都很困難.

    ③帶索引小字庫法.即將欲顯示文件中的漢字字模,從標準字庫中逐一提取固化,製成小型字庫,並按其在小字庫中的位置製成索引表,顯示時從索引表查出其新的字模取碼地址,取碼顯示.此方法雖比較靈活,可顯示較多的漢字,但仍然侷限於只能顯示固定文件內容,且字模製取同樣麻煩.

    一種較新的單片機"漢字動態編碼與顯示方案"(見《單片機與嵌入式系統應用》雜誌2003年第1期和第9期),實際上也是一種動態的"小字庫"法,只是字庫的製取,索引的編寫及文件的改碼皆由PC機自動完成,免去了繁瑣的人工處理.

    由上可見,目前單片機各種漢字顯示方案均不理想.標準字庫法,單片機不堪重負;而其它方法最大且又無法克服的缺點是,所顯示文字皆有侷限.顯示內容也皆須專業人員設計而定,用戶難於更改.這便極大地限制了單片機在各個領域的開拓和應用.究其原因,皆爲單片機本身無漢卡,而這也正是我們致力於"51漢卡"開發的初衷.

    2.13×14點陣漢字字模

    爲墊定"5l漢卡"的字型基礎,首先開發成了l3×14點陣漢字字模.在目前通用的漢字字模中,最簡單的是16×16點陣字模.在微型打字機中,也偶見有12×12點陣字模,但實用中不多見.字模點陣數直接決定着每一漢字所佔單元內存值,能否在保證字模準確、美觀的基礎上,尋找一種較少的點陣字模呢?這便是我們最初的想法.於是我們經過反覆選擇比較,終於在國內首個推出了13×14點陣字模.此設計,一是基於我國漢字爲方塊字,故其行、列值需相近;二是漢字多有對稱1生,故其列值宜奇不宜偶.設計實際表明,若行、列值很少,則難保證字模的準確性和美觀性.?

    13×14點陣字模,是以我國現行簡化字爲準,並在此基礎上設計而成.與目前通用的漢字16×l6點陣字模相比,其準確性和美觀性並不遜色.然而其單字所佔內存卻由32個單元降至26個單元;另外使得每個單字顯示由原來的256個像素降至l82個像素,使顯示成本和空間均減少近三分之一.100×200點陣LED字屏,可顯示16×l6點陣漢字72個,而l3×14點陣漢字便可顯示l05個,且顯示效果並無太大差異.這無疑對單片機和嵌入式系統漢字顯示產品的開發和應用,具有明顯的經濟價值和實用意義.

    3.51單片機13×14點陣縮碼漢卡

    "51漢卡"依據我國的漢字特點和單片機的快速構字功能,在13×14點陣字模基礎上,以縮碼形式開發而成單片機漢卡的開發,應以目前通用的主流單片機爲研發對象,還應在囊括國標一、二級漢字及常用字符的前提下,使內存佔用必須降至主流單片機可尋址範圍內,且需留有足夠的檢字程序和用戶應用空間.另外,字模設計必須準確、美觀.字模提取速度也必須滿足實用要求."51漢卡"的開發正是依據原則,並達到了以上各項要求.

    顧名思義,"51漢卡,即以MCS-51系列及其兼容單片機爲研發對象.以51系列爲代表的8位單片機,在過去、現在以及可以予見的將來,都將是嵌入式系統低端應用的主流機型.此乃業界專家的共識.

    "51漢卡"囊括了"GB2312-80"國標字庫的全部一、二級漢字,並增補漢字86個;同時包括了大、小英文字母、阿拉伯數字等160個常用字符和不到4KB的構字程序,卻僅總共佔用了不足66KB的內存.每字平均約佔9.8個單元,相對於16×16點陣每字佔32單兀內存而言,尚不到其三分之一.這對於具有相互獨立的64KB程序區和64KB數據區的51系列單片機而言,若適當配置內存,可爲檢字程序和用戶留出90%以上的程序空間及相當數量的數據空間,對於一般用戶的應用,都將綽綽有餘.

    另外,爲使"51漢卡''更便於使用和進一步節省內存,在上述基礎上又開發成一套簡化版本,刪去了部分較偏僻的二級漢字.簡化版本包括約5580個漢字,共佔用內存58KB.實際上,按有關權威部門的統計,一般文本99%的文字是由2400個字寫成的,因此使用簡化版本,並配以簡單的造字程序,一般亦可滿足我們的使用要求.

    "51漢卡"所用字模,即我們開發的完全可與16×16點陣字模媲美的I3×14點陣漢字字模.字模提取速度是我們最爲關心的問題之一.經測試及實際使用表明,"51漢卡''的提模速度完全可滿足單片機漢字顯示的實用要求.

    我們使用INTEL公司MCS-51經典系列87C51單片機在24MHz頻率下測試,平均字模提取速度爲2.1ms/字.因人的視覺暫留時間爲0.1s,無論理論還是實際使用都表明,50字字模提取並顯示,並無遲滯和待機之感.即使在1?2MHz頻率下,20字取模,即點即出,在一般拼音檢字和少量漢字顯示中,完全可滿足使用要求.隨着單片機技術的迅速發展,目前,INTEL公司、Atmel公司、philips公司、我國臺灣華邦等公司生產的MCS-51兼容單片機時鐘頻率可達33MHz,增強型可達40MHz,以至達60MHz;現市售的"STC89LE"系列單片機,最高頻率可達90MHz.這些芯片都完全能與MCS-51芯片兼容,對於更高需求的場合,更新升級也十分簡便.另外,在單片機和嵌入式系統中,文字顯示速度要求並不高,只要滿足換屏時的視覺要求即可.其漢字顯示字數,一般也不太多.如用LCD顯示屏,128×64點陣,才顯示32個字;192×64點陣才顯48個字;即使使用l3×14點陣字模,滿屏也才56個漢字.

    4."51漢卡"設計依據及說明

    "51漢卡"設計依據是,我國漢字雖然數量繁多,字型各異,但其中複合結構者佔大部分,並素有"偏旁取義,正字取音"之說.如"寸"字與不同偏旁可組成"村"、"付"、"討"、"守"、"過"等字.因此"51漢卡"除單結構字基本以全碼設計外,復臺結構字多用相應的單體字及其偏旁,以結構代碼寫成.利用單片機快速的單元積木式構字程序,便可迅速生成字模代碼.這既保證了提碼速度,又節省了大量的漢卡內存.

    有關"51漢卡"的幾點說明如下:

    ①凡漢字庫中簡、繁體字都有的用簡體.如"後"以"後"代,"餘"以"餘"代等;

    ②《新華字典》未收入字,多未收入,如"酏"、"鼽"等字,但"婧"、"弳"等字仍收入;

    ③對於多體字,一般以常用字代,如"摺"以"折"代,"鏇"以"旋,代等,但"吒"不以"吒"代,"讎"不以"仇"代等;

    ④對通常已由其它字取代的字,都以這些字代替,如"崬"以"東"代,"肛''以"船"代等;

    ⑤二級漢字中,不單獨構成漢字的偏旁未收入;

    ⑥依據名篇名著,生活用語等,增補漢字86個;

    ⑦收編大、小寫英文字母、阿拉伯數字、標點符號等各種常用字符160個.

    5."51單片機漢卡"應用舉例

    利用"51單片機漢卡",將使51系列單片機的漢字顯示輕而易舉,並可大爲降低成本、體積和設計開發的難度,爲單片機在生產控制、信息通信、文化教育和日常生活等領域,特別是計算機終端和手持產品的開發提供極大的便利和支持.?

    我們現已初步開發成"51漢卡"的"區位碼輸入法"和"拼音輸入法,檢字程序,並利用"51漢卡"成功地開發了帶有廉價單片機控制器的LED漢字顯示屏.這不僅大幅度降低了成本費用.而且用戶可以通過單片機控制器,隨心所欲地改變顯示內容.

    51硬件設計

    CPU--87C51、12MHz晶振.

 

    程序存儲器一1片EPROM?27C512.

    數據存儲器一1片EPROM?27C512;1片EEPROM28C64A;1片6116.

    控制器顯示屏一LCD?HY一19264B(深圳秋田視佳實業有限公司).

    LED屏選240×16點陣.

    本系統用標準小鍵盤檢字,一次可予選4000字;控制器LCD滿屏顯示l3×14點陣漢字56個;LED屏滿屏顯示漢字19個.

    地址分配及用途如表l所列.

    5.2程序設計框圖

    程序設計流程如圖1所示.本系統採用12MHz晶振,若LCD取滿屏56字,換屏時有約0.1s的延時,這對人的實際視覺並無大影響.

標準點陣漢字字庫芯片

回到頂部

    1 概述

    GT23L24M1W是一款內含24X24點陣的漢字庫芯片,支持GB18030國標漢字(含有國家信標委合法授

    權)及ASCII字符.排列格式爲橫置橫排.用戶通過字符內碼,利用本手冊提供的方法計算出該字符點陣

    在芯片中的地址,可從該地址連續讀出字符點陣信息.

    1.1 芯片特點

    ●  數據總線: SPI 串行總線接口

    PLII 精簡地址並行總線接口

    ●  點陣排列方式:字節橫置橫排

    訪問速度:SPI 時鐘頻率:20MHz(max.)

    PLII 訪問速度:130ns(max.) @3.3V

    ●  工作電壓:2.7V~3.6V

    ●  電流:工作電流:12mA

    待機電流:10uA

    ●  封裝:SO20W

    ●  尺寸(SO20W):12.80mmX10.30mm

    ●  工作溫度:-20℃~85℃(SPI 模式下);-10℃~85℃(PLII 模式下)

    1.2 字庫內容

    字型樣張

    2 引腳描述與接口連接

    2.1 引腳名稱

    2.2 SPI 接口引腳描述

    串行數據輸出(SO):該信號用來把數據從芯片串行輸出,數據在時鐘的下降沿移出.

    串行數據輸入(SI):該信號用來把數據從串行輸入芯片,數據在時鐘的上升沿移入.

    串行時鐘輸入(SCLK):數據在時鐘上升沿移入,在下降沿移出.

    片選輸入(CS#):所有串行數據傳輸開始於CE#下降沿,CE#在傳輸期間必須保持爲低電平,在兩條

    指令之間保持爲高電平.

    總線掛起輸入(HOLD#):

    2.3 SPI 接口與主機接口電路示意圖

    SPI 與主機接口電路連接可以參考下圖(#HOLD管腳建議接 2K 電阻 3.3V 拉高).

    若是採用系統電壓爲 5V的,則需要進行電平轉換匹配連接 GT23 芯片,可以參考下圖(#HOLD 管腳建議接 2K 電阻 3.3V 拉高).

    2.4 PLII 接口引腳描述

    2.5 PLII 接口與主機接口電路示意圖

    SPI/PLII_SEL(管腳內部有 100K 上拉電阻)接地,字庫芯片選擇 PLII 接口模式,與主機接口電路連接可以參考下圖.

    2.6 PLII 總線接口尋址說明

    在 PLII 總線模式下,芯片內部有 3個地址寄存器,主機需要把要讀取數據的地址寫入這 3個地址寄存器,然後再從數據寄存器中讀出數據.主機每讀一次數據寄存器,芯片內部的地址寄存器會自動增一,從而使主機只寫一次首地址,就可以連續讀取數據.

    3 字庫調用方法

    3.1 漢字點陣排列格式

    每個漢字在芯片中是以漢字點陣字模的形式存儲的,每個點用一個二進制位表示,存 1的點,當顯示

    時可以在屏幕上顯示亮點,存 0的點,則在屏幕上不顯示.點陣排列格式爲橫置橫排:即一個字節的高位

    表示左面的點,低位表示右面的點(如果用戶按 word mode讀取點陣數據,請注意高低字節的順序),排

    滿一行的點後再排下一行.這樣把點陣信息用來直接在顯示器上按上述規則顯示,則將出現對應的漢字.

    3.1.1  24X24點漢字排列格式

    24X24 點漢字的信息需要 72個字節(BYTE 0 – BYTE 71)來表示.該 24X24 點漢字的點陣數據是

    橫置橫排的,其具體排列結構如下圖:

    命名規則:

    最大字符集及字數

    S:GB2312 6,763漢字

    M:GB18030 27,484漢字

    T:GB12345  6,866漢字

    BIG5  5,401 / 13,060漢字

    U:Unicode V3.0  27,484漢字

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章