摘要:
在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 < Bytes;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大小的限制了。