教程不斷更新中:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429
第28章 emWin6.x的C文件格式的漢字生成和實現(Unicode編碼)
本章節主要為大家講解官方的字體生成軟件FontCvt的使用方法,使用此軟件可以生成C文件格式的漢字全字庫,也可以生成C文件格式的小字庫,所謂小字庫就是需要顯示什么漢字就僅生成這些漢字。
FontCvt全稱Font Converter。
28.1 初學者重要提示
28.2 使用FontCvt生成字庫C文件的方法
28.3 C文件格式漢字的使用方法
28..4生成的是Unicode編碼字體,而使用時為什么是UTF-8
28.5 MDK4.X,MDK5.X和IAR的UTF-8編碼問題
28.6 實驗例程說明(RTOS)
28.7 實驗例程說明(裸機)
28.8 總結
28.1 初學者重要提示
1、 emWin官方提供的字體生成軟件FontCvt不支持GB編碼,所以只能使用FontCvt支持的Unicode編碼。
2、 字體小工具需要使用此貼提供的,其它大部分是Demo版本:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=107218 。
3、 教程中讓大家將要顯示漢字的C文件轉換為UTF-8編碼,指的是將這個漢字所在的C文件轉換為UTF-8編碼,這點要切記,詳情請看28.4小節的說明。
另外特別注意MDK5編譯錯誤missing closing quote,解決辦法看本章教程第28.6.2小節。
4、 FontCvt的使用方法在emWin手冊中有講解,這個只有英文版手冊進行了詳細說明:
28.2 使用FontCvt生成C文件格式小字庫的方法
所謂小字庫就是需要顯示什么漢字就僅生成什么漢字,下面為大家講解如何生成C文件格式的小字庫。這里以生成“安富萊電子”五個字為例進行說明。
- 第1步:在電腦桌面右擊鼠標->新建->文本文檔,即新建一個txt文本。
創建了文本文檔后,輸入“安富萊電子”五個字:
然后點擊菜單選項文件->另存為:
彈出如下窗口:
(注:Win10選擇的是UTF-16 LE)
此時桌面上就會生成一個名字為FontSong16的文本文檔。
- 第2步:打開字體生成軟件FontCvt,選擇字體類型Standard,編碼選擇16bit Unicode
點擊OK后,彈出如下窗口:
再點擊確定后彈出FontCvt界面變成如下效果:
- 第3步:點擊EDIT->Disable all characters
禁止所有字符后,字符區就全部變成灰色的了:
- 第4步:點擊Edit->Read pattern file
- 第5步:加載文件FontSong16.txt
點擊打開后,FontCvt軟件的字符顯示區中“安富萊電子”五個字的背景已經變成白色,下面是其中一個“萊”字的顯示效果:
- 第6步:最后一步,點擊File->Save As
彈出如下窗口:
至此就生成了我們所需要的16點陣字體。以同樣的方法,我們再以此生成以下幾種字體:
1. 字體類型Standard,16bit Unicode編碼,32點陣,宋體,生成的文件名為FontSong32.c。
2. 字體類型Standard,16bit Unicode編碼,72點陣,宋體,生成的文件名為FontSong72.c。
3. 字體類型Standard,16bit Unicode編碼,144點陣,宋體,生成的文件名為FontSong144.c。
4. 字體類型Antialiased 4bpp(4倍抗鋸齒),16bit Unicode編碼,144點陣,宋體,生成的文件名為FontSongA144.c。
5. 字體類型Extended framed(擴展模式,帶邊框),16bit Unicode編碼,144點陣,宋體,生成的文件名為FontSongExF144.c。
6. 字體類型Extended antialiased 4bpp(擴展模式,4倍抗鋸齒),16bit Unicode編碼,144點陣,宋體,生成的文件名為FontSongExA144.c。
通過小軟件FontCvt,共生成了7種字體文件:
有了這幾個文件就可以進行相應字體的漢字顯示了,由於僅生成了“安富萊電子”這五個字,所以僅支持這五個字的顯示。接下來講解這7種字體文件如何使用。
28.3 使用FontCvt生成C文件格式全字庫的方法
由於FontCvt生成C文件格式的全字庫比較大,放在內部Flash非常占空間,所以基本不使用,不過生成方法要簡單說明下。
- 第1步:打開字體生成軟件FontCvt,選擇字體類型Standard,編碼選擇16bit Unicode
點擊OK后,彈出如下窗口:
再點擊確定后彈出FontCvt界面變成如下效果:
- 第2步:點擊File->Save As
彈出如下窗口:
此時,桌面上就生成了一個名為FontSong16.c的文件,實際在MDK工程中測試,此文件要占用1147060字節,即1MB多,所以實際項目中不推薦。
28.4 C文件格式漢字的使用方法
下面講解28.2小節生成的7種字體C文件的使用方法,這里將MDK和IAR分別進行說明:
28.4.1 MDK編譯器中使用C文件格式漢字的方法
- 第1步:將生成的7種字體文件添加到MDK工程目錄里面,本章節配套的例子是將其放在User->fonts文件夾下
- 第2步:將生成的7種字體文件添加到MDK工程中
- 第3步:調用函數GUI_UC_SetEncodeUTF8()來使能UTF-8編碼,這一步是必須的,切不可以忘了。
- 第4步:此時就可以使用這7種字體了,打開這7個字體文件,每個文件的開頭都有一個extern的字體聲明。
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong16;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong32;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong72;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong144;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongA144;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExA144;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExF144;
如果用戶要在哪個源碼文件里面使用這些字體,就把這些字體聲明放在相應源文件的開頭就行。使用方法,跟使用emWin自帶的ASCII和ISO 8859-1字體基本是一樣的,唯一區別的地方是:調用FontCvt生成的字體時要加上取地址操作&。下面舉一個完整的例子,代碼在本章節配套例子的MainTask.c文件里面(對於初學者來說,對話框,按鈕控件和文本控件還沒有講到,這里只是舉個例子,會使用這些新生成的字體即可,后面會講到這些控件):
#include "MainTask.h" #include "includes.h" /* ********************************************************************************************************* * 調用外部字體聲明,這個就是第4步中所說的問題 ********************************************************************************************************* */ extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong16; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong32; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong72; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong144; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongA144; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExA144; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExF144; /* ********************************************************************************************************* * 對話框資源列表 ********************************************************************************************************* */ static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = { { FRAMEWIN_CreateIndirect, "armfly", 0, 0, 0, 800,480,FRAMEWIN_CF_MOVEABLE,0}, { BUTTON_CreateIndirect, "安富萊我們我們", GUI_ID_BUTTON0, 350,20,420,150,0,0}, { TEXT_CreateIndirect, "安富萊電子", GUI_ID_TEXT0, 5, 10, 300, 33, 0,0}, { TEXT_CreateIndirect, "安富萊電子", GUI_ID_TEXT1, 5, 40,250, 50, 0,0}, { TEXT_CreateIndirect, "安富萊", GUI_ID_TEXT2, 5, 100,360, 90, 0,0}, { TEXT_CreateIndirect, "富", GUI_ID_TEXT3, 5, 220,144, 144, 0,0}, { TEXT_CreateIndirect, "富", GUI_ID_TEXT4, 205, 230,144, 144, 0,0}, { TEXT_CreateIndirect, "富", GUI_ID_TEXT5, 405, 230,144, 144, 0,0}, { TEXT_CreateIndirect, "富", GUI_ID_TEXT6, 605, 230,144, 144, 0,0} }; /* ********************************************************************************************************* * 函 數 名: PaintDialog * 功能說明: 對話框重繪函數 * 形 參:pMsg 消息指針 * 返 回 值: 無 ********************************************************************************************************* */ void PaintDialog(WM_MESSAGE * pMsg) { // WM_HWIN hWin = pMsg->hWin; } /* ********************************************************************************************************* * 函 數 名: 對話框初始化 * 功能說明: 對話框初始化 * 形 參: pMsg 消息指針 * 返 回 值: 無 ********************************************************************************************************* */ void InitDialog(WM_MESSAGE * pMsg) { WM_HWIN hWin = pMsg->hWin; // // 配置FrameWin // FRAMEWIN_SetFont(hWin,&GUI_Font32B_ASCII); FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER); FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0); FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1); FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2); FRAMEWIN_SetTitleHeight(hWin,35); /* 外部的7種字體在文件控件TEXT和按鈕控件BUTTON中都使用了,具體調用方法如下, 跟使用emWin自帶的字體是一樣的。*/ // // 按鈕的字體是4倍抗鋸齒,144點陣 // BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&GUI_FontFontSongA144); // // 分別用16點陣,32點陣和72點陣字體顯示 安富萊電子 五個字。 // TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontFontSong16); TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_GREEN); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&GUI_FontFontSong32); TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&GUI_FontFontSong72); // // 分別用144點陣漢字,144點陣的擴展模式且4倍抗鋸齒漢字,144點陣的4倍抗鋸齒漢字和 // 144點陣的擴展模式且帶邊框漢字。 // TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&GUI_FontFontSong144); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT4),&GUI_FontFontSongExA144); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT5),&GUI_FontFontSongA144); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT6),&GUI_FontFontSongExF144); } /* ********************************************************************************************************* * 函 數 名: _cbCallback * 功能說明: 對話框回調函數 * 形 參: pMsg 消息指針 * 返 回 值: 無 ********************************************************************************************************* */ static void _cbCallback(WM_MESSAGE * pMsg) { int NCode, Id; WM_HWIN hWin = pMsg->hWin; switch (pMsg->MsgId) { case WM_PAINT: PaintDialog(pMsg); break; case WM_INIT_DIALOG: InitDialog(pMsg); break; case WM_KEY: switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) { case GUI_KEY_ESCAPE: GUI_EndDialog(hWin, 1); break; case GUI_KEY_ENTER: GUI_EndDialog(hWin, 0); break; } break; case WM_NOTIFY_PARENT: Id = WM_GetId(pMsg->hWinSrc); NCode = pMsg->Data.v; switch (Id) { case GUI_ID_OK: if(NCode==WM_NOTIFICATION_RELEASED) GUI_EndDialog(hWin, 0); break; case GUI_ID_CANCEL: if(NCode==WM_NOTIFICATION_RELEASED) GUI_EndDialog(hWin, 0); break; } break; default: WM_DefaultProc(pMsg); } } /* ********************************************************************************************************* * 函 數 名: MainTask * 功能說明: GUI主函數 * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */ void MainTask(void) { /* 初始化 */ GUI_Init(); WM_MULTIBUF_Enable(1); /* 使能UTF-8編碼,這個是第3步中所說的問題,不必限制一定要放在這個位置,使用外部字體之前調用了即可 */ GUI_UC_SetEncodeUTF8(); /* 調用此函數會自動的刷新桌面窗口 */ WM_SetDesktopColor(GUI_WHITE); /* 創建對話框 */ GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0); while(1) { GUI_Delay(10); } }
通過上面的代碼就實現了這7種字體的顯示,具體效果可以看實驗例程說明。
- 第5步:這個是最重要的一步,很多初學者顯示漢字失敗就是因為這一步了。
修改漢字顯示所在的源文件,即MainTask.c文件為UTF-8編碼,並不是修改FontCvt生成的C文件為UTF-8編碼,因為FontCvt軟件生成的C文件已經是UTF-8編碼了。也就是說哪個文件用到這種漢字顯示了,哪個文件就修改編碼類型為UTF-8,只有這樣,MDK才可以將這些漢字的編碼識別出來,要不識別出來的漢字編碼與FontCvt生成字體的編碼類型不匹配,從而無法正確顯示。
修改編碼類型也比較容易,使用電腦自帶的記事本即可,將MainTask.C文件用記事本打開:
點擊文件->另存為
彈出如下窗口:
點擊保存后,會彈出如下窗口:
重新切換回MDK工程,也會彈出一個窗口:
這樣MainTask.c文件就變成UTF-8編碼了。此時就可以全編譯工程並下載例子到開發板進行測試了。
28.4.2 IAR編譯器中使用C文件格式漢字的方法
- 第1步:將生成的7種字體文件添加到IAR工程目錄里面,本章節配套的例子是將其放在User->fonts文件夾下
- 第2步:將生成的7種字體文件添加到IAR工程中
- 第3步:調用函數GUI_UC_SetEncodeUTF8()來使能UTF-8編碼,這一步是必須的,切不可以忘了。
- 第4步:此時就可以使用這7種字體了,打開這7個字體文件,每個文件的開頭都有一個extern的字體聲明。
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong16;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong32;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong72;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong144;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongA144;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExA144;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExF144;
如果用戶要在哪個源碼文件里面使用這些字體,就把這些字體聲明放在相應源文件的開頭就行。使用方法,跟使用emWin自帶的ASCII和ISO 8859-1字體基本是一樣的,唯一區別的地方是:調用FontCvt生成的字體時要加上取地址操作&。下面舉一個完整的例子,代碼在本章節配套例子的MainTask.c文件里面(對於初學者來說,對話框,按鈕控件和文本控件還沒有講到,這里只是舉個例子,會使用這些新生成的字體即可,后面會講到這些控件):
#include "MainTask.h" #include "includes.h" /* ********************************************************************************************************* * 調用外部字體聲明,這個就是第4步中所說的問題 ********************************************************************************************************* */ extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong16; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong32; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong72; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSong144; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongA144; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExA144; extern GUI_CONST_STORAGE GUI_FONT GUI_FontFontSongExF144; /* ********************************************************************************************************* * 對話框資源列表 ********************************************************************************************************* */ static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = { { FRAMEWIN_CreateIndirect, "armfly", 0, 0, 0, 800,480,FRAMEWIN_CF_MOVEABLE,0}, { BUTTON_CreateIndirect, "安富萊我們我們", GUI_ID_BUTTON0, 350,20,420,150,0,0}, { TEXT_CreateIndirect, "安富萊電子", GUI_ID_TEXT0, 5, 10, 300, 33, 0,0}, { TEXT_CreateIndirect, "安富萊電子", GUI_ID_TEXT1, 5, 40,250, 50, 0,0}, { TEXT_CreateIndirect, "安富萊", GUI_ID_TEXT2, 5, 100,360, 90, 0,0}, { TEXT_CreateIndirect, "富", GUI_ID_TEXT3, 5, 220,144, 144, 0,0}, { TEXT_CreateIndirect, "富", GUI_ID_TEXT4, 205, 230,144, 144, 0,0}, { TEXT_CreateIndirect, "富", GUI_ID_TEXT5, 405, 230,144, 144, 0,0}, { TEXT_CreateIndirect, "富", GUI_ID_TEXT6, 605, 230,144, 144, 0,0} }; /* ********************************************************************************************************* * 函 數 名: PaintDialog * 功能說明: 對話框重繪函數 * 形 參:pMsg 消息指針 * 返 回 值: 無 ********************************************************************************************************* */ void PaintDialog(WM_MESSAGE * pMsg) { // WM_HWIN hWin = pMsg->hWin; } /* ********************************************************************************************************* * 函 數 名: 對話框初始化 * 功能說明: 對話框初始化 * 形 參: pMsg 消息指針 * 返 回 值: 無 ********************************************************************************************************* */ void InitDialog(WM_MESSAGE * pMsg) { WM_HWIN hWin = pMsg->hWin; // // 配置FrameWin // FRAMEWIN_SetFont(hWin,&GUI_Font32B_ASCII); FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER); FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0); FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1); FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2); FRAMEWIN_SetTitleHeight(hWin,35); /* 外部的7種字體在文件控件TEXT和按鈕控件BUTTON中都使用了,具體調用方法如下, 跟使用emWin自帶的字體是一樣的。*/ // // 按鈕的字體是4倍抗鋸齒,144點陣 // BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&GUI_FontFontSongA144); // // 分別用16點陣,32點陣和72點陣字體顯示 安富萊電子 五個字。 // TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontFontSong16); TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_GREEN); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&GUI_FontFontSong32); TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&GUI_FontFontSong72); // // 分別用144點陣漢字,144點陣的擴展模式且4倍抗鋸齒漢字,144點陣的4倍抗鋸齒漢字和 // 144點陣的擴展模式且帶邊框漢字。 // TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&GUI_FontFontSong144); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT4),&GUI_FontFontSongExA144); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT5),&GUI_FontFontSongA144); TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT6),&GUI_FontFontSongExF144); } /* ********************************************************************************************************* * 函 數 名: _cbCallback * 功能說明: 對話框回調函數 * 形 參: pMsg 消息指針 * 返 回 值: 無 ********************************************************************************************************* */ static void _cbCallback(WM_MESSAGE * pMsg) { int NCode, Id; WM_HWIN hWin = pMsg->hWin; switch (pMsg->MsgId) { case WM_PAINT: PaintDialog(pMsg); break; case WM_INIT_DIALOG: InitDialog(pMsg); break; case WM_KEY: switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) { case GUI_KEY_ESCAPE: GUI_EndDialog(hWin, 1); break; case GUI_KEY_ENTER: GUI_EndDialog(hWin, 0); break; } break; case WM_NOTIFY_PARENT: Id = WM_GetId(pMsg->hWinSrc); NCode = pMsg->Data.v; switch (Id) { case GUI_ID_OK: if(NCode==WM_NOTIFICATION_RELEASED) GUI_EndDialog(hWin, 0); break; case GUI_ID_CANCEL: if(NCode==WM_NOTIFICATION_RELEASED) GUI_EndDialog(hWin, 0); break; } break; default: WM_DefaultProc(pMsg); } } /* ********************************************************************************************************* * 函 數 名: MainTask * 功能說明: GUI主函數 * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */ void MainTask(void) { /* 初始化 */ GUI_Init(); WM_MULTIBUF_Enable(1); /* 使能UTF-8編碼,這個是第3步中所說的問題,不必限制一定要放在這個位置,使用外部字體之前調用了即可 */ GUI_UC_SetEncodeUTF8(); /* 調用此函數會自動的刷新桌面窗口 */ WM_SetDesktopColor(GUI_WHITE); /* 創建對話框 */ GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0); while(1) { GUI_Delay(10); } }
通過上面的代碼就實現了這7種字體的顯示,具體效果可以看實驗例程說明。
- 第5步:這個是最重要的一步,很多初學者顯示漢字失敗就是因為這一步了。
修改漢字顯示所在的源文件,即MainTask.c文件為UTF-8編碼,並不是修改FontCvt生成的C文件為UTF-8編碼,因為FontCvt軟件生成的C文件已經是UTF-8編碼了。也就是說哪個文件用到這種漢字顯示了,哪個文件就修改編碼類型為UTF-8,只有這樣,IAR將這些漢字的編碼識別出來,要不識別出來的漢字編碼與FontCvt生成字體的編碼類型不匹配,從而無法正確顯示。
修改編碼類型也比較容易,使用IAR的話,不要使用記事本來修改了(為什么不可以使用,在28.5小節有講解),IAR編輯器支持編碼類型的修改。
IAR編碼方面的小知識:
默認情況下,IAR創建的工程都是System編碼,也就是你的電腦系統是什么編碼類型,使用IAR創建的.C和.H文件就是什么編碼類型,一般大陸都是用的GBK編碼,查看電腦系統編碼類型可以通過:單擊開始->所有程序->附件->命令提示符,打開命令提示符,輸入chcp,然后點擊鍵盤的回車鍵。
這里的936就是代表GBK編碼。而IAR的編碼設置在這里,點擊菜單Tools->Options,彈出如下窗口
默認的編碼類型是System。
在IAR編譯器中如何查看.C和.H文件的編碼類型,又如何修改呢?查看編碼類型可以任意打開一個文件,然后查看右下角。
這里打開的就是一個中文簡體,GB2312編碼,GBK向下是完全兼容GB2312的。修改單個.C和.H文件的編碼類型也比較簡單,這里我們需要修改MainTask.c文件的編碼類型為UTF-8,直接在MainTask.c文件里面右擊鼠標,選擇Character Encoding->Convert to UTF-8。
設置后就可以看到右下角已經修改為UTF-8了。
此時就可以全編譯工程並下載例子到開發板進行測試了。
28.5 生成的是Unicode編碼字體,而使用時為什么是UTF-8
初學者容易有這樣的疑問,FontCvt軟件生成的是Unicode編碼的漢字,為什么emWin使用的時候不直接使用,還要多一次轉換,即我們操作的時候是用的UTF-8編碼字體,emWin的庫函數會將這個編碼轉換成Unicode編碼,然后從Unicode編碼的字符集中獲取相應的點陣數據。
補充點小知識,方便大家理解:
- Unicode編碼
各個國家都有一套自己的編碼標准,但誰也不懂誰的編碼,誰也不支持別人的編碼。基於此,國際組織決定着手解決這個問題,即重新弄一套包括了地球上所有文化、所有字母和符號的編碼。將其命名為"UniversalMultiple-Octet Coded Character Set“(通用多八位編碼字符集),簡稱 UCS, 俗稱Unicode。Unicode有兩種編碼UCS-2和UCS-4,其中UCS-2用兩個字節編碼,UCS-4用4個字節編碼。
- UTF-8編碼
事實證明,對可以用ASCⅡ表示的字符使用UNICODE並不高效,因為UNICODE比ASCⅡ占用大一倍的空間,而對ASCⅡ來說高字節的0對他毫無用處。為了解決這個問題,就出現了一些中間格式的字符集,他們被稱為通用轉換格式,即UTF(Universal Transformation Format)。目前存在的UTF格式有:UTF-7,UTF-7.5,UTF-8,UTF-16以及 UTF-32。
那么問題來了,emWin中為什么不直接使用Unicode編碼,而要使用UTF-8。
1. MDK和IAR的編輯器都不支持Unicode編碼,僅支持UTF-8,筆者認為,這個是最主要的原因。
2. UTF-8編碼相對於Unicode編碼的優勢。
(1) UTF-8表示與ASCII字符表示是一樣的,只占一個字節,解決了Unicode浪費空間的情況。
(2) 與CPU字節順序無關, 可以在不同平台之間交流。
(3) 容錯能力高, 任何一個字節損壞后, 最多只會導致一個編碼碼位損失, 不會連鎖錯誤。
28.6 MDK4.X,MDK5.X和IAR的UTF-8編碼問題
對於初學者來說,下面的問題是必看的,初次看可能不太理解,實際用這三個編譯器操作了本章節配套的例子就有深刻的體會了。
28.6.1 MDK4.X的UTF-8說明
MDK4.74是MDK4系列里面的最后一個版本了。
一直以來都是將漢字顯示所在的源文件使用記事本另存為UTF-8編碼類型,特別注意,記事本另存的是UTF-8 帶 BOM。且用戶修改了這個文件的任何地方,MDK都會自動將這個文件存儲為UTF-8編碼無BOM。實際用Notepad++另存為UTF-8帶BOM或者不帶BOM,使用MDK4.74都可以正確顯示漢字的。
28.6.2 MDK5.X的UTF-8說明
對於MDK5.X來說,也可以使用記事本將漢字顯示所在的源文件另存為UTF-8編碼類型,此時MDK5.21a是可以正確編譯的。但是,用戶一旦修改了這個文件的任何地方,直接編譯或者保存后編譯,MDK都會將這個文件存儲為UTF-8編碼無BOM,而MDK5.X無法像MDK4.X那樣帶BOM或者不帶BOM都能夠識別,所以編譯會出錯。解決方法:options->c/c++->Misc controls 填寫“--locale=english”
28.6.3 IAR的UTF-8說明
對於IAR來說,他僅支持UTF-8無BOM,修改的時候不要使用記事本,直接在漢字顯示所在的源文件右擊選擇即可(在28.4.2小節已經講解),或者用Notepad++選擇UTF-8無BOM。
28.6.4 編碼問題總結
- IAR僅支持UTF-8編碼無BOM文件的漢字顯示,帶BOM的話,編譯不通過。
- MDK4.X對於UTF-8帶BOM或者不帶BOM都支持,但會將帶BOM文件修改為不帶BOM,兩種編碼形式顯示漢字都不受影響。
- MDK5.X對於UTF-8帶BOM或者不帶BOM都支持,不過需要大家按照28.6.2小結的說明修改。
名詞解釋:BOM
BOM(Byte Order Mark),字節順序標記,出現在文本文件頭部,Unicode編碼標准中用於標識文件是采用哪種格式的編碼。UTF-8 不需要 BOM 來表明字節順序,但可以用 BOM 來表明編碼方式。字符 "Zero Width No-Break Space" 的 UTF-8 編碼是 EF BB BF。所以如果接收者收到以 EF BB BF 開頭的字節流,就知道這是 UTF-8編碼了。Windows 就是使用 BOM 來標記文本文件的編碼方式的。
WINDOWS自帶的記事本等軟件,在保存一個以UTF-8編碼的文件時,會在文件開始的地方插入三個不可見的字符(0xEF 0xBB 0xBF,即BOM)。它是一串隱藏的字符,用於讓記事本等編輯器識別這個文件是否以UTF-8編碼。
28.7 實驗例程說明(RTOS)
配套例子:
V7-532_emWin6.x實驗_C文件格式的漢字生成和實現,Unicode編碼(RTOS)
實驗目的:
- 學習emWin的C文件格式漢字的使用方法,Unicode編碼。
- emWin功能的實現在MainTask.c文件里面。
實驗內容:
1、K1按鍵按下,串口或者RTT打印任務執行情況(串口波特率115200,數據位8,奇偶校驗位無,停止位1)。
2、(1) 凡是用到printf函數的全部通過函數App_Printf實現。
(2) App_Printf函數做了信號量的互斥操作,解決資源共享問題。
3、默認上電是通過串口打印信息,如果使用RTT打印信息:
MDK AC5,MDK AC6或IAR通過使能bsp.h文件中的宏定義為1即可
#define Enable_RTTViewer 1
4、各個任務實現的功能如下:
App Task Start 任務 :啟動任務,這里用作BSP驅動包處理。
App Task MspPro任務 :消息處理,這里用作LED閃爍。
App Task UserIF 任務 :按鍵消息處理。
App Task COM 任務 :暫未使用。
App Task GUI 任務 :GUI任務。
μCOS-III任務調試信息(按K1按鍵,串口打印):
RTT 打印信息方式:
程序設計:
- 任務棧大小分配:
μCOS-III任務棧大小在app_cfg.h文件中配置:
#define APP_CFG_TASK_START_STK_SIZE 512u
#define APP_CFG_TASK_MsgPro_STK_SIZE 2048u
#define APP_CFG_TASK_COM_STK_SIZE 512u
#define APP_CFG_TASK_USER_IF_STK_SIZE 512u
#define APP_CFG_TASK_GUI_STK_SIZE 2048u
任務棧大小的單位是4字節,那么每個任務的棧大小如下:
App Task Start 任務 :2048字節。
App Task MspPro任務 :8192字節。
App Task UserIF 任務 :2048字節。
App Task COM 任務 :2048字節。
App Task GUI 任務 :8192字節。
- 系統棧大小分配:
μCOS-III的系統棧大小在os_cfg_app.h文件中配置:
#define OS_CFG_ISR_STK_SIZE 512u
系統棧大小的單位是4字節,那么這里就是配置系統棧大小為2KB
emWin動態內存配置:
GUIConf.c文件中的配置如下:
#define EX_SRAM 1/*1 used extern sram, 0 used internal sram */ #if EX_SRAM #define GUI_NUMBYTES (1024*1024*24) #else #define GUI_NUMBYTES (100*1024) #endif
通過宏定義來配置使用內部SRAM還是外部的SDRAM做為emWin的動態內存,當配置:
#define EX_SRAM 1 表示使用外部SDRAM作為emWin動態內存,大小24MB。
#define EX_SRAM 0 表示使用內部SRAM作為emWin動態內存,大小100KB。
默認情況下,本教程配套的所有emWin例子都是用外部SDRAM作為emWin動態內存。
emWin界面顯示效果:
800*480分辨率界面效果。
28.8 實驗例程說明(裸機)
配套例子:
V7-531_emWin6.x實驗_C文件格式的漢字生成和實現,Unicode編碼(裸機)
實驗目的:
- 學習emWin的C文件格式漢字的使用方法,Unicode編碼。
- emWin功能的實現在MainTask.c文件里面。
emWin界面顯示效果:
800*480分辨率界面效果。
emWin動態內存配置:
GUIConf.c文件中的配置如下:
#define EX_SRAM 1/*1 used extern sram, 0 used internal sram */ #if EX_SRAM #define GUI_NUMBYTES (1024*1024*24) #else #define GUI_NUMBYTES (100*1024) #endif
通過宏定義來配置使用內部SRAM還是外部的SDRAM做為emWin的動態內存,當配置:
#define EX_SRAM 1 表示使用外部SDRAM作為emWin動態內存,大小24MB。
#define EX_SRAM 0 表示使用內部SRAM作為emWin動態內存,大小100KB。
默認情況下,本教程配套的所有emWin例子都是用外部SDRAM作為emWin動態內存。
28.9 總結
本章節講解的內容較多,特別是涉及到UTF-8編碼的問題時,望初學者務必將其掌握,有了本章節的基礎,后面幾個章節的漢字顯示操作起來將更加的得心應手。