如何将ucgui的汉字库存放到外部的flash-crazytyt-ChinaUnix博客

2025-04-16 13:21:14
推荐回答(1个)
回答1:

在ARM7系统中,都不会有足够大的程序存储器来存放大容量的汉字库,因此当系统中要用到汉字库时,需要将其存储在外部的FLASH Memory,而ucgui的字符显示函数是直接从程序存储器取数据的,因此需要在原始代码里增加一个接口,来指向外部的FLASH Memory。
  简介:
  ucgui中,字符显示的底层函数是 GUICharP.c 中的 void GUIPROP_DispChar(U16P c) 函数,我们将这个函数修改如下:
  /*********************************************************************
  *
  * GUIPROP_DispChar
  *
  * Purpose:
  * This is the routine that displays a character. It is used by all
  * other routines which display characters as a subroutine.
  */

  void GUIPROP_DispChar(U16P c) {
  int BytesPerLine;
  U8 BytesPerFont; //一个字的字节数
  U32 base,oft; //字库的起始地址和偏移量

  GUI_DRAWMODE DrawMode = GUI_Context.TextMode;
  const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUIPROP_FindChar(GUI_Context.pAFont->p.pProp, c);
  if (pProp) {
  GUI_DRAWMODE OldDrawMode;
  const GUI_CHARINFO GUI_UNI_PTR * pCharInfo;
  //支持3种字体==
  if((GUI_Context.pAFont == &GUI_FontHZ16)||(GUI_Context.pAFont == &GUI_FontHZ24)||(GUI_Context.pAFont == &GUI_FontHZ32))
  {
  pCharInfo = pProp->paCharInfo;

  base = (U32)pProp->paCharInfo->pData;
  BytesPerFont = GUI_Context.pAFont->YSize * pProp->paCharInfo->BytesPerLine; //每个字模的数据字节数
  if (BytesPerFont > BYTES_PER_FONT)
  {
  BytesPerFont = BYTES_PER_FONT;
  }
  if (c < 0x80) //英文字符地址偏移算法
  {
  oft = base + (c - 0x20) * BytesPerFont; //计算出字码在flash中的偏移地址
  } else //中文字符地址偏移算法 {
  oft = base + (((c>>8) - 0xa1) * 94 + ((c&0xff) - 0xa1)) * BytesPerFont;

  }
  LCD_ReadFlashBit(oft, GUI_FontDataBuf, BytesPerFont);//取出字模数据

  BytesPerLine = pCharInfo->BytesPerLine;
  OldDrawMode = LCD_SetDrawMode(DrawMode);

  LCD_DrawBitmap( GUI_Context.DispPosX,
  GUI_Context.DispPosY,
  pCharInfo->XSize,
  GUI_Context.pAFont->YSize,
  GUI_Context.pAFont->XMag,
  GUI_Context.pAFont->YMag,
  1, /* Bits per Pixel */
  BytesPerLine,
  GUI_FontDataBuf,
  &LCD_BKCOLORINDEX
  );
  }
  //--
  else
  {
  pCharInfo = pProp->paCharInfo+(c-pProp->First);
  BytesPerLine = pCharInfo->BytesPerLine;
  OldDrawMode = LCD_SetDrawMode(DrawMode);
  LCD_DrawBitmap( GUI_Context.DispPosX,
  GUI_Context.DispPosY,
  pCharInfo->XSize,
  GUI_Context.pAFont->YSize,
  GUI_Context.pAFont->XMag,
  GUI_Context.pAFont->YMag,
  1, /* Bits per Pixel */
  BytesPerLine,
  pCharInfo->pData,
  &LCD_BKCOLORINDEX
  );
  }

  /* Fill empty pixel lines */
  if (GUI_Context.pAFont->YDist > GUI_Context.pAFont->YSize) {
  int YMag = GUI_Context.pAFont->YMag;
  int YDist = GUI_Context.pAFont->YDist * YMag;
  int YSize = GUI_Context.pAFont->YSize * YMag;
  if (DrawMode != LCD_DRAWMODE_TRANS) {
  LCD_COLOR OldColor = GUI_GetColor();
  GUI_SetColor(GUI_GetBkColor());
  LCD_FillRect(GUI_Context.DispPosX,
  GUI_Context.DispPosY + YSize,
  GUI_Context.DispPosX + pCharInfo->XSize,
  GUI_Context.DispPosY + YDist);
  GUI_SetColor(OldColor);
  }
  }
  LCD_SetDrawMode(OldDrawMode); /* Restore draw mode */
  GUI_Context.DispPosX += pCharInfo->XDist * GUI_Context.pAFont->XMag;
  }
  }
  然后再加入FLASH操作的底层驱动(这里用的是SPI FLASH)
  /*********************************************************************
  *
  * Static code
  *
  **********************************************************************
  */
  //字模数据的暂存数组,以单个字模的最大字节数为设定值
  #define BYTES_PER_FONT 4*32 //最大支持32*32的汉字
  static U8 GUI_FontDataBuf[BYTES_PER_FONT];

  /*********************************************************************
  *
  * 读FLASH中的字库
  */
  #include "spi_flash.h"
  #include "ssp.h"

  void LCD_ReadFlashBit(U32 addr,U8* buf,U8 Bytes)
  {
  U8 i;
  SPI_FLASH_StartReadSequence(addr); //设置起始地址
  for(i=0;i
  {
  buf[i] = SPI_FLASH_SendByte(0xa5);
  }
  SPI_FLASH_CS_HIGH();
  }
  我们知道,ucgui访问字库的时候,是根据字库文件的索引表来查找汉字数据地址的,因此汉字库文件中的索引也要修改,以汉字库32为例
  /*
  ******************************************************

  File Name : hzk32.C
  Compiler :
  Author : Liu_xf
  Version : V1.0
  Date : 2011-3-28 11:25:54
  Description :
  ucgui的中文字库,与uc工具生成的字库文件不同的是,可以将
  大容量的汉字数组存入到外部的FALSH里
  当然这个也是由uc工具生成的文件修改而来的。
  *******************************************************
  Structure :

  History:

  *******************************************************
  */

  #include "..\core\GUI.H"
  #ifndef GUI_FLASH
  #define GUI_FLASH
  #endif
  extern GUI_FLASH const GUI_FONT GUI_FontHZ32;

  /*
  GUI_FLASH const GUI_CHARINFO GUI_FontHZ32_CharInfo[] = {
  { 10, 10, 1, (void GUI_FLASH *)0}, // 字符在FLASH中的偏移量
  { 16, 16, 2, (void GUI_FLASH *)3840}, //汉字在FLASH中的偏移量
  };
  */

  GUI_FLASH const GUI_CHARINFO GUI_FontHZ32_CharInfo[] = {
  // Y X X_BYTE
  { 16, 8, 1, (void GUI_FLASH *)0}, // FLASH里没有存字符,这里为0
  { 32, 32, 4, (void GUI_FLASH *)GUI_FontHZ32_Flash_BaseAddr}, //GUI_FontHZ32_Flash_BaseAddr在GUI.h中定义
  };

  //汉字和字符索引表//////////////////////////////////

  /*鳌--齄*/

  GUI_FLASH const GUI_FONT_PROP GUI_FontHZ32_Propf7a1= {
  0xf7a1,
  0xf7fe,
  &GUI_FontHZ32_CharInfo[1],
  (void *)0
  };

  //.....这里省略若干,详见符件里的代码

  /* --〓*/
  GUI_FLASH const GUI_FONT_PROP GUI_FontHZ32_Propa1a1= {
  0xa1a1,
  0xa1fe,
  &GUI_FontHZ32_CharInfo[1],
  (void *)&GUI_FontHZ32_Propa2a1
  };
  //ASC字符
  /* --*/
  GUI_FLASH const GUI_FONT_PROP GUI_FontHZ32_Prop0020= {
  0x0020,
  0x007f,
  &GUI_FontHZ32_CharInfo[0],
  (void *)&GUI_FontHZ32_Propa1a1
  };
  GUI_FLASH const GUI_FONT GUI_FontHZ32 = {
  GUI_FONTTYPE_PROP_SJIS,
  32,
  32,
  1,
  1,
  (void GUI_FLASH *)&GUI_FontHZ32_Prop0020
  };
  在GUI.H中添加汉字库在flash中的首地址,及字库声明
  /*汉字*/
  //汉字库在FLASH中的首地址
  #define GUI_FontHZ16_Flash_BaseAddr 0x0
  #define GUI_FontHZ24_Flash_BaseAddr 0x00045080
  #define GUI_FontHZ32_Flash_BaseAddr 0x000E05A0

  extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ16;
  extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ24;
  extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ32;
  然后将字库下载到SPI FLASH中,注意三个字库的起始地址与GUI.h中定义的应该是一样的。还有字库生成时,也应该是标准的汉字库,满足 oft = base + (((c>>8) - 0xa1) * 94 + ((c&0xff) - 0xa1)) * BytesPerFont; 的计算方式。
  
  结语:
  有了将汉字库定义到外部FLASH的方法,则可以定义任意汉字库,不受程序FLASH大小的限制了。