一、漢字區位碼、國標碼和機內碼
1、區位碼
為了使每一個漢字有一個全國統一的代碼,1980年,我國頒布了第一個漢字編碼的國家標准: GB2312-80《信息交換用漢字編碼字符集》基本集,這個字符集是我國中文信息處理技術的發展基礎,也是目前國內所有漢字系統的統一標准。
所有的國標漢字與符號組成一個94×94的矩陣。在此方陣中,每一行稱為一個"區",每一列稱為一個"位",因此,這個方陣實際上組成了一個有94個區(區號分別為0 1到94)、每個區內有94個位(位號分別為01到94)的漢字字符集。一個漢字所在的區號和位號簡單地組合在一起就構成了該漢字的"區位碼"。在漢字的區位碼中,高兩位為區號,低兩位為位號。
在區位碼中,01-09區為682個特殊字符,16~87區為漢字區,包含6763個漢字 。其中16-55區為一級漢字(3755個最常用的漢字,按拼音字母的次序排列),56-87區為二級漢字(3008個漢字,按部首次序排列)。
需要注意的是:區位碼通常都是用十進制表示的,例如“誠”字的區位碼為1947,也就說它位於19區第47個字符。
摘自:《漢字區位碼》
2、國標碼
國家標准代碼,簡稱國標碼,是中華人民共和國的中文常用漢字編碼集。國家標准強制標准冠以“GB”。
現時中華人民共和國官方強制使用GB 18030標准,但較舊的計算機仍然使用GB 2312。國標碼 = 區位碼(16進制化--區碼和位碼分別進行16進制轉化)+2020H
3、機內碼
計算機只識別由0、1組成的代碼,ASCII碼是英文信息處理的標准編碼,漢字信息處理也必須有一個統一的標准編碼。 漢字交換碼(國標碼)主要用於漢字信息交換,我國國家標准局於1981年5月頒布了《信息交換用漢字編碼字符集——基本集》,代號為GB2312-80,共對6763個漢字和682個圖形字符進行了編碼。
其編碼原則為:漢字用兩個字節表示,原則上,兩個字節可以表示 256×256=65536 種不同的符號,作為漢字編碼表示的基礎是可行的。但考慮到漢字編碼與其它國際通用編碼,如ASCII 西文字符編碼的關系,我國國家標准局采用了加以修正的兩字節漢字編碼方案,只用了兩個字節的低7位。這個方案可以容納128×128=16384 種不同的漢字,但為了與標准ASCII碼兼容,每個字節中都不能再用32個控制功能碼和碼值為32的空格以及127的操作碼。所以每個字節只能有94個編碼。這樣,雙七位實際能夠表示的字數是:94×94=8836個。
機內碼 = 國標碼 + 8080H
機內碼 = 區位碼(16進制化--區碼和位碼分別進行16進制轉化) + a0a0H摘自:《機內碼》
4、相互轉換
- 內碼轉換為區位碼
區位碼: 區碼=內碼高字節-0xa0
位碼=內碼低字節-0xa0
例如:“國”內碼為:0xb9,0xfa
16進制表示的區位碼:0x19,0x5a
其區位碼(默認為10進制):2590
- 區位碼轉換為內碼
內碼: 內碼高字節=區碼+0xa0
內碼低字節=位碼+0xa0
例如:“海”區位碼為:2603
16進制表示的區位碼:0x1a,0x03
其內碼(默認為16進制):0xba,0xa3
二、字模
漢字在顯示的時候,是以點陣的形式顯示出來的,常見到的有16*16點陣、24*24點陣、32*32點陣。比如說“啊”的16*16點陣字模如下,共256Bits,占用32 Bytes:
0x00,0x00,0xf7,0x7e,0x95,0x04,0x95,0x04,0x96,0x74,0x96,0x54,0x95,0x54,0x95,0x54, 0x95,0x54,0xf5,0x54,0x97,0x74,0x04,0x04,0x04,0x04,0x05,0x04,0x04,0x14,0x04,0x08
字模顯示的時候,以兩個字節表示一行像素點,16行就構成了一個完整的字模。屏幕在顯示的時候,1顯示為亮色,0顯示為背景色,這樣就能把字體顯示出來。用C測試程序,把1的地方顯示為“*”,0的地方顯示為空,效果如下:
三、字庫
字庫,就是所有漢字字模的集合。顯然,在編排這些字模的時候需要一定的順序(規則),而這個規則就是“機內碼”。根據機內碼的漢字布局,將對應的漢字字模進行整合,形成字庫文件。在使用的時候,應用程序根據漢字的機內碼,從字庫中找到對應的存儲位置,取出字模,進行顯示。機內碼就是漢字在字庫中的索引。
在區位碼中,01-09區為682個特殊字符,16~87區為漢字區,有效漢字6768個。在制作字庫的時候把特殊字符刪除,只使用有效漢字區。也就是說我們從第16區的第1位開始進行字模收集,當第16區收集結束,緊接着收集第17區,直到第87區編排結束。總共收集6768個漢字,占用空間216576 Bytes。
☆ 機內碼與字庫偏移量的關系
偏移量 = ((機內碼高字節-0xb0)*94+機內碼低字節-0xa1)*32
四、測試程序

#include <stdio.h> void ShowOneWord(const char *str); int GetGBKCode(unsigned char* pBuffer,const char * c); void ShowWords(const char *str); /** * @brief main function * @param Nove * @retval Nove */ int main(void){ ShowWords("測試漢字顯示"); return 0; } /** * @brief Show multiple Chinese Words * @param str : point to Chinese location code * @retval Nove */ void ShowWords(const char *str){ if(NULL == str) return; while(*str != 0){ ShowOneWord(str); str += 2; } } /** * @brief Show one Chinese Word * @param str : point to Chinese location code * @retval Nove */ void ShowOneWord(const char *str){ unsigned char buffer[32]; int i,j; unsigned char k; GetGBKCode(buffer,str); for(i=0;i<16;i++){ for(j=0;j<8;j++){ k = buffer[2*i] << j; if(k & 0x80){ printf("*"); } else{ printf(" "); } } for(j=0;j<8;j++){ k = buffer[2*i+1] << j; if(k & 0x80){ printf("*"); } else{ printf(" "); } } printf("\n"); } printf("\n\n"); } /** * @brief Get type matrix from HZLIB.bin based on Chinese location code * @param pBuffer: point to 32 bytes type matrix buffer * c : point to Chinese location code * @retval 0(success) -1(fail) */ int GetGBKCode(unsigned char* pBuffer,const char * c){ unsigned char High8bit,Low8bit; unsigned int pos; FILE * fp; High8bit=*c; Low8bit=*(c+1); pos = ((High8bit-0xa0-16)*94+Low8bit-0xa0-1)*2*16; //get type matrix location fp =fopen("HZLIB.bin","r"); //open type matrix file if (fp != NULL) { fseek (fp,pos,SEEK_SET); //set read start point fread(pBuffer,1,32,fp); //read 32 bytes fclose(fp); return 0; } else return -1; }
五、注意
1、漢字在程序中是以機內碼進行表示,英文字符則是ASCII,漢字的機內碼占兩個字節
2、漢字表示的時候,以雙引號括起來代表一個字符串,只有一個漢字的字符串,實際占用3個字節的存儲空間。
附eclipse測試代碼: Chinese_Test.zip
參考資料:《STM32庫開發實戰指南》