微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 第19章 汉字显示方式二(放到外部存储器)

第19章 汉字显示方式二(放到外部存储器)

时间:10-02 整理:3721RD 点击:

第19章 汉字显示方式二(放到外部存储器)


    本期教程主要讲如何将字库放置到外部存储器的方法,这里以放到SD卡为例,放到其他存储器是一样的。本章教程提供的方法是以前UCGUI时代遗留下来的,这种方法相对于后面要讲到的XBF方式还是有差距的(官方推荐方式)。不过为了照顾以前从UCGUI转战过来的,写了这么一期教程。

    19. 1  移植方法

    19. 2 总结


19.1 移植方法
19.1.1 第一步:添加相关文件

    在工程的emWin文件夹中新建一个HanZi文件夹,主要有以下几个文件:





19.1.2 第二步:将这几个文件添加到工程




19.1.3 第三步:GUI_UC_EncodeNone.c文件内容

  1. #include "GUI_Private.h"

  2. /*********************************************************************
  3. *
  4. *       Static code
  5. *
  6. **********************************************************************
  7. */
  8. /*********************************************************************
  9. *
  10. *       _GetCharCode
  11. *
  12. * Purpose:
  13. *   Return the UNICODE character code of the current character.
  14. */
  15. static U16 _GetCharCode(const char GUI_UNI_PTR * s) {
  16.   if((*s) > 0xA0)
  17.   {
  18.     return *(const U16 GUI_UNI_PTR *)s;
  19.   }
  20.   return *(const U8 GUI_UNI_PTR *)s;
  21. }

  22. /*********************************************************************
  23. *
  24. *       _GetCharSize
  25. *
  26. * Purpose:
  27. *   Return the number of bytes of the current character.
  28. */
  29. static int _GetCharSize(const char GUI_UNI_PTR * s) {
  30.   GUI_USE_PARA(s);
  31.   if((*s) > 0xA0)
  32.   {
  33.     return 2;
  34.   }
  35.   return 1;
  36. }

  37. /*********************************************************************
  38. *
  39. *       _CalcSizeOfChar
  40. *
  41. * Purpose:
  42. *   Return the number of bytes needed for the given character.
  43. */
  44. static int _CalcSizeOfChar(U16 Char) {
  45.   GUI_USE_PARA(Char);
  46.   if(Char > 0xA0A0)
  47.   {
  48.     return 2;
  49.   }
  50.   return 1;
  51. }

  52. /*********************************************************************
  53. *
  54. *       _Encode
  55. *
  56. * Purpose:
  57. *   Encode character into 1/2/3 bytes.
  58. */
  59. static int _Encode(char *s, U16 Char) {
  60.   if(Char > 0xA0A0)
  61.   {
  62.     *((U16 *)s) = (U16)(Char);
  63.     return 2;
  64.   }
  65.   *s = (U8)(Char);
  66.   return 1;
  67. }

  68. /*********************************************************************
  69. *
  70. *       Static data
  71. *
  72. **********************************************************************
  73. */
  74. /*********************************************************************
  75. *
  76. *       _API_Table
  77. */
  78. const GUI_UC_ENC_APILIST GUI__API_TableNone = {
  79.   _GetCharCode,     /*  return character code as U16 */
  80.   _GetCharSize,     /*  return size of character: 1 */
  81.   _CalcSizeOfChar,  /*  return size of character: 1 */
  82.   _Encode           /*  Encode character */
  83. };

  84. const GUI_UC_ENC_APILIST GUI_UC_None = {
  85.   _GetCharCode,     /*  return character code as U16 */
  86.   _GetCharSize,     /*  return size of character: 1 */
  87.   _CalcSizeOfChar,  /*  return size of character: 1 */
  88.   _Encode           /*  Encode character */
  89. };

  90. /*********************************************************************
  91. *
  92. *       Exported code
  93. *
  94. **********************************************************************
  95. */
  96. /*********************************************************************
  97. *
  98. *       GUI_UC_SetEncodeNone
  99. */
  100. //void GUI_UC_SetEncodeNone(void) {
  101. //  GUI_LOCK();
  102. //  GUI_pContext->pUC_API = &GUI__API_TableNone;
  103. //  GUI_UNLOCK();
  104. //}

复制代码



19.1.4  第四步:GUICharPEx.c文件内容

  1. #include <stddef.h>           /* needed for definition of NULL */
  2. #include "GUI_Private.h"
  3. #include "ff.h"
  4. #include "bsp.h"
  5. #include "MainTask.h"
  6. #include "string.h"


  7. /* 字模数据的暂存数组,以单个字模的最大字节数为设定值 */
  8. #define BYTES_PER_FONT      1024
  9. static U8 GUI_FontDataBuf[BYTES_PER_FONT];

  10. /*
  11.    用于12*12和16*16电子汉字的路径部分,要和其它汉字路径作区分
  12.    使用sizeof的时候,得指定数组的大小。
  13. */
  14. const char FontEx_HZ[22] = {"0:/system/gui_font/HZ1"};

  15. FIL fsrc;        // 定义文件操作类  
  16. FRESULT res;     // 定义操作结果变量  
  17. UINT bw1;         // 定义读写数量变量
  18. /*---------------------------------------------------------------------------*/
  19. /*字库外部函数部分-----------------------------------------------------------*/
  20. void GUI_X_GetFontData(char* font, U32 oft, U8 *ptr, U16 bytes)
  21. {
  22.     res = f_open(&fsrc, font, FA_OPEN_EXISTING | FA_READ);   //打开字库文件   
  23.     if(res != FR_OK)   
  24.     {   

  25.     }   
  26.     res = f_lseek(&fsrc,oft); //找到首地址  
  27.     res = f_read(&fsrc, ptr, bytes, &bw1); //读取32个字库点阵数据
  28. res = f_close(&fsrc); //关闭字体  

  29. }

  30. static void GUI_GetDataFromMemory(const GUI_FONT_PROP GUI_UNI_PTR *pProp, U16P c)
  31. {
  32.     U16 BytesPerFont;
  33.     U32 oft;
  34. char *font = (char *)pProp->paCharInfo->pData;

  35. /* 每个字模的数据字节数 */
  36.     BytesPerFont = GUI_pContext->pAFont->YSize * pProp->paCharInfo->BytesPerLine;
  37.     if (BytesPerFont > BYTES_PER_FONT)
  38. {
  39. BytesPerFont = BYTES_PER_FONT;
  40. }
  41. /* 英文字符地址偏移算法 */
  42.     if (c < 0x80)                                                               
  43.     {
  44. oft = (c-0x20) * BytesPerFont;
  45.     }
  46.     else                                                                           
  47.     {

  48. if(strncmp(FontEx_HZ, font, sizeof(FontEx_HZ)) == 0) (1)
  49. {
  50. /* 中文字符地址偏移算法包括符号 */
  51. oft = ((((c >> 8)-0xA1)) + ((c & 0xFF)-0xA1) * 94)* BytesPerFont;
  52. }
  53. else
  54. {
  55. /* 中文字符地址偏移算法包括符号 */
  56. oft = ((((c >> 8)-0xA1)) + ((c & 0xFF)-0xB0) * 94)* BytesPerFont;
  57. }

  58.     }


  59. GUI_X_GetFontData(font, oft, GUI_FontDataBuf, BytesPerFont);

  60. }

  61. void GUIPROP_X_DispChar(U16P c)  
  62. {
  63.     int BytesPerLine;
  64.     GUI_DRAWMODE DrawMode = GUI_pContext->TextMode;
  65.     const GUI_FONT_PROP GUI_UNI_PTR *pProp = GUI_pContext->pAFont->p.pProp;
  66.     //搜索定位字库数据信息  
  67.     for (; pProp; pProp = pProp->pNext)                                          
  68.     {
  69.         if ((c >= pProp->First) && (c <= pProp->Last))break;
  70.     }
  71.     if (pProp)
  72.     {
  73.         GUI_DRAWMODE OldDrawMode;
  74.         const GUI_CHARINFO GUI_UNI_PTR * pCharInfo = pProp->paCharInfo;
  75.         GUI_GetDataFromMemory(pProp, c);//取出字模数据
  76.         BytesPerLine = pCharInfo->BytesPerLine;               
  77.         OldDrawMode  = LCD_SetDrawMode(DrawMode);
  78.         LCD_DrawBitmap(GUI_pContext->DispPosX, GUI_pContext->DispPosY,
  79.                        pCharInfo->XSize, GUI_pContext->pAFont->YSize,
  80.                        GUI_pContext->pAFont->XMag, GUI_pContext->pAFont->YMag,
  81.                        1,     /* Bits per Pixel */
  82.                        BytesPerLine,
  83. &GUI_FontDataBuf[0],
  84. &LCD_BKCOLORINDEX
  85.                        );
  86.         /* Fill empty pixel lines */
  87.         if (GUI_pContext->pAFont->YDist > GUI_pContext->pAFont->YSize)
  88.         {
  89.             int YMag = GUI_pContext->pAFont->YMag;
  90.             int YDist = GUI_pContext->pAFont->YDist * YMag;
  91.             int YSize = GUI_pContext->pAFont->YSize * YMag;
  92.             if (DrawMode != LCD_DRAWMODE_TRANS)
  93.             {
  94.                 LCD_COLOR OldColor = GUI_GetColor();
  95.                 GUI_SetColor(GUI_GetBkColor());
  96.                 LCD_FillRect(GUI_pContext->DispPosX, GUI_pContext->DispPosY + YSize,
  97.                              GUI_pContext->DispPosX + pCharInfo->XSize,
  98.                              GUI_pContext->DispPosY + YDist);
  99.                 GUI_SetColor(OldColor);
  100.             }
  101.         }
  102.         LCD_SetDrawMode(OldDrawMode); /* Restore draw mode */
  103. //      if (!GUI_MoveRTL)
  104.         GUI_pContext->DispPosX += pCharInfo->XDist * GUI_pContext->pAFont->XMag;
  105.     }
  106. }

  107. /*********************************************************************
  108. *
  109. *       GUIPROP_GetCharDistX
  110. */
  111. int GUIPROP_X_GetCharDistX(U16P c)
  112. {
  113.     const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUI_pContext->pAFont->p.pProp;  
  114.     for (; pProp; pProp = pProp->pNext)                                         
  115.     {
  116.         if ((c >= pProp->First) && (c <= pProp->Last))break;
  117.     }
  118.     return (pProp) ? (pProp->paCharInfo)->XSize * GUI_pContext->pAFont->XMag : 0;
  119. }

复制代码

1. 这个地方非常重要,讲之前先介绍下外置到SD卡中的字体。

    12*12点阵汉字和字符  使用的是UCDOS里面的,半角和全角字符显示都正常,汉字也正常

        偏移地址计算:oft = ((((c >> 8)-0xA1)) + ((c & 0xFF)-0xA1) * 94)* BytesPerFont;

    16*16点阵汉字和字符  使用的是UCDOS里面的,半角和全角字符显示都正常,汉字也正常

        偏移地址计算:oft = ((((c >> 8)-0xA1)) + ((c & 0xFF)-0xA1) * 94)* BytesPerFont;

    24*24点阵汉字和字符  使用的是UCDOS里面的,半角显示正常,字库里面全角字符需要单独添加。偏移地址计算:oft = ((((c >> 8)-0xA1)) + ((c & 0xFF)-0xB0) * 94)* BytesPerFont; 注意和前两个的不同。主要是因为这个里面只有汉字。最重要的是这个字体居然显示的时候是躺在的,而且上下镜像。

    48*48点阵汉字和字符  使用的是UCDOS里面的,半角显示正常,字库里面全角字符,需要单独添加。 偏移地址计算:oft = ((((c >> 8)-0xA1)) + ((c & 0xFF)-0xB0) * 94)* BytesPerFont; 注意和前两个的不同。主要是因为这个里面只有汉字。

    SD卡中存放的字库如下(路径0:/system/gui_font):



    特别注意24*24和48*48汉字点阵库中没有加全角字符,而12*12和16*16中添加了,所以就出现了上面程序中的区别对待。用路径的前22个字符0:/system/gui_font/HZ1就可以区分开。


19.1.5  第五步:字库文件

下面的是GUI_Font12.c中的内容,其它类似:

  1. #include "GUI.h"

  2. extern void GUIPROP_X_DispChar(U16P c);
  3. extern int GUIPROP_X_GetCharDistX(U16P c);

  4. GUI_CONST_STORAGE GUI_CHARINFO GUI_FontHZ12_CharInfo[2] =    (1)
  5. {     
  6.     {  6,    6,  1, (void *)"0:/system/gui_font/ASC6x12.bin"},      
  7.     {  12,  12,  2, (void *)"0:/system/gui_font/HZ12x12.bin"},         
  8. };
  9. GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ12_PropHZ= {
  10.       0xA1A1,  
  11.       0xFEFE,  
  12. &GUI_FontHZ12_CharInfo[1],
  13.       (void *)0,  
  14. };
  15. GUI_CONST_STORAGE  GUI_FONT_PROP GUI_FontHZ12_PropASC= {
  16.       0x0000,  
  17.       0x007F,  
  18. &GUI_FontHZ12_CharInfo[0],
  19.       (void GUI_CONST_STORAGE *)&GUI_FontHZ12_PropHZ,  
  20. };
  21. GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ12 =  
  22. {
  23.   GUI_FONTTYPE_PROP_USER,
  24.       12,  
  25.       12,  
  26.       1,   
  27.       1,   
  28.       (void GUI_CONST_STORAGE *)&GUI_FontHZ12_PropASC
  29. };

  30. GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ12x2 =  
  31. {
  32. GUI_FONTTYPE_PROP_USER,
  33.       12,  
  34.       12,  
  35.       2,   
  36.       2,   
  37.       (void GUI_CONST_STORAGE *)&GUI_FontHZ12_PropASC
  38. };

复制代码

1. 要修改文件存放的路径,需要修改这里和GUICharPEx文件中的:

       const char FontEx_HZ[22] = {"0:/system/gui_font/HZ1"};


19.1.6  第六步:在GUI_Type.h中添加声明

  1. #define GUI_FONTTYPE_PROP_USER        \
  2.             GUIPROP_X_DispChar,       \
  3.             (GUI_GETCHARDISTX *) GUIPROP_X_GetCharDistX,   \
  4.             GUIMONO_GetFontInfo,      \
  5.             GUIMONO_IsInFont,         \
  6.            (GUI_GETCHARINFO *)0,      \
  7.            (tGUI_ENC_APIList*)0

复制代码


19.1.7 第七步:添加主函数

  1. #include "includes.h"
  2. #include "MainTask.h"


  3. extern GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ48;

  4. /*
  5. *********************************************************************************************************
  6. *        对话框信息
  7. *********************************************************************************************************
  8. */
  9. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  10.     { FRAMEWIN_CreateIndirect,  "armfly",              0,          0,  0,  800,480,FRAMEWIN_CF_MOVEABLE,0},
  11.     { BUTTON_CreateIndirect,    "安富莱电子armfly",               GUI_ID_BUTTON0,          40,320,700,100,0,0},
  12. { BUTTON_CreateIndirect,    "世界人民欢迎你Eric2013",        GUI_ID_BUTTON1,          40,200,700,100,0,0},
  13.     { TEXT_CreateIndirect,      "armfly安富莱电子armfly",   GUI_ID_TEXT0,            5, 10, 200, 33, 0,0},
  14.     { TEXT_CreateIndirect,      "armfly安富莱电子armfly",   GUI_ID_TEXT1,            5, 40,200, 33, 0,0},
  15.     { TEXT_CreateIndirect,      "安富莱电子armfly",               GUI_ID_TEXT2,            5, 80,360, 72, 0,0},
  16. };

  17. /*
  18. *********************************************************************************************************
  19. *        函 数 名: PaintDialog
  20. *        功能说明: 重绘
  21. *        形    参:pMsg  消息指针
  22. *        返 回 值: 无
  23. *********************************************************************************************************
  24. */
  25. void PaintDialog(WM_MESSAGE * pMsg)
  26. {
  27.     WM_HWIN hWin = pMsg->hWin;
  28. }

  29. /*
  30. *********************************************************************************************************
  31. *        函 数 名: InitDialog
  32. *        功能说明: 对话框初始化
  33. *        形    参:pMsg  消息指针
  34. *        返 回 值: 无
  35. *********************************************************************************************************
  36. */
  37. void InitDialog(WM_MESSAGE * pMsg)
  38. {
  39.     WM_HWIN hWin = pMsg->hWin;
  40.     //
  41.     //FRAMEWIN
  42.     //
  43.     FRAMEWIN_SetFont(hWin,&GUI_Font32B_ASCII);
  44.     FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
  45.     FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);
  46.     FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);
  47.     FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);
  48.     FRAMEWIN_SetTitleHeight(hWin,35);
  49.     //
  50.     //GUI_ID_BUTTON0
  51.     //
  52.     BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&GUI_FontHZ48);
  53. BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON1),&GUI_FontHZ48);
  54.     //
  55.     //GUI_ID_TEXT0
  56.     //
  57. TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED);
  58. TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontHZ12);
  59. TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_GREEN);
  60. TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&GUI_FontHZ16);
  61. TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
  62. TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&GUI_FontHZ24);
  63. }

  64. /*
  65. *********************************************************************************************************
  66. *        函 数 名: _cbCallback
  67. *        功能说明: 对话框回调函数
  68. *        形    参:pMsg  消息指针
  69. *        返 回 值: 无
  70. *********************************************************************************************************
  71. */
  72. static void _cbCallback(WM_MESSAGE * pMsg)
  73. {
  74.     int NCode, Id;
  75.     WM_HWIN hWin = pMsg->hWin;
  76.     switch (pMsg->MsgId)
  77.     {
  78.         case WM_PAINT:
  79.             PaintDialog(pMsg);
  80.             break;
  81.         case WM_INIT_DIALOG:
  82.             InitDialog(pMsg);
  83.             break;
  84.         case WM_KEY:
  85.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  86.             {
  87.                 case GUI_KEY_ESCAPE:
  88.                     GUI_EndDialog(hWin, 1);
  89.                     break;
  90.                 case GUI_KEY_ENTER:
  91.                     GUI_EndDialog(hWin, 0);
  92.                     break;
  93.             }
  94.             break;
  95.         case WM_NOTIFY_PARENT:
  96.             Id = WM_GetId(pMsg->hWinSrc);
  97.             NCode = pMsg->Data.v;        
  98.             switch (Id)
  99.             {
  100.                 case GUI_ID_OK:
  101.                     if(NCode==WM_NOTIFICATION_RELEASED)
  102.                         GUI_EndDialog(hWin, 0);
  103.                     break;
  104.                 case GUI_ID_CANCEL:
  105.                     if(NCode==WM_NOTIFICATION_RELEASED)
  106.                         GUI_EndDialog(hWin, 0);
  107.                     break;

  108.             }
  109.             break;
  110.         default:
  111.             WM_DefaultProc(pMsg);
  112.     }
  113. }


  114. /*
  115. *********************************************************************************************************
  116. *        函 数 名: MainTask
  117. *        功能说明: GUI主函数
  118. *        形    参:无
  119. *        返 回 值: 无
  120. *********************************************************************************************************
  121. */
  122. void MainTask(void)
  123. {
  124.     GUI_Init();
  125.     WM_SetDesktopColor(GUI_WHITE);       /* Automacally update desktop window */
  126.     WM_SetCreateFlags(WM_CF_MEMDEV);     /* Use memory devices on all windows to avoid flicker */
  127. PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
  128. FRAMEWIN_SetDefaultSkin(FRAMEWIN_SKIN_FLEX);
  129. PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
  130. BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX);
  131. CHECKBOX_SetDefaultSkin(CHECKBOX_SKIN_FLEX);
  132. DROPDOWN_SetDefaultSkin(DROPDOWN_SKIN_FLEX);
  133. SCROLLBAR_SetDefaultSkin(SCROLLBAR_SKIN_FLEX);
  134. SLIDER_SetDefaultSkin(SLIDER_SKIN_FLEX);
  135. HEADER_SetDefaultSkin(HEADER_SKIN_FLEX);
  136. RADIO_SetDefaultSkin(RADIO_SKIN_FLEX);
  137.     GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
  138. while(1)
  139. {
  140. GUI_Delay(10);
  141. }
  142. }

复制代码

实际显示效果如下:



    特别注意,如果使用的是800*480分辨率的屏可以完全显示出来,如果是小于这个分辨率的屏只能显示出一部分,大家可以按照上面的设计方法做一个适合自己屏大小的显示或者直接拖动这个对话框即可。


19.2 总结

    本期教程就为大家讲这么多,这种方法大家有个了解即可,由于考虑到还有很多从UCGUI转战过来的,而且很多项目都是用的这种方式,所以特此做了本期教程。如果对这个方法没有了解的,可以放弃这种显示方法了,因为有更好的XBF方式。


19.2总结
本期教程就为大家讲这么多,这种方法大家有个了解即可,由于考虑到还有很多从UCGUI转战过来的,而且很多项目都是用的这种方式,所以特此做了本期教程。如果对这个方法没有了解的,可以放弃这种显示方法了,因为有更好的XBF方式。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top