emWin图形库由德国SEGGER公司开发的嵌入式GUI。用STM32及NXP系列MCU设计时,可以免费获得编译好的emWin库。
emWin默认是不支持中文显示的,如果要用到中文显示,只有自己添加了。
在工程中添加如下几个文件:ASCII_CODE.c、GUI_Font.c.、GUI_UC_EncodeNone.c、GUICharPEx.c。
在ASCII_CODE.c中写入如下两个数组用与存储对应汉字字体的半角ASCII字符点阵:
const unsigned char ASCII_08X16[95][16]= {1608ASCII字符点阵码,对应16X16汉字};
const unsigned char ASCII_12X24[95][48] = {2412ASCII字符点阵码,对应24X24汉字};
在GUI_Font.c文件中填入以下代码:
#include "GUI.H"
#ifndef GUI_FLASH
#define GUI_FLASH
#endif
#define HZ_16X16 0x00000 //16x16汉字字库在FALSH中存储的偏移地址
#define HZ_24X24 0x40000 //24x24汉字字库在FALSH中存储的偏移地址
extern void GUIPROP_HZ_DispChar(U16P c);
extern int GUIPROP_HZ_GetCharDistX(U16P c, int * pSizeX);
extern const unsigned char ASCII_08X16[95][16];
extern const unsigned char ASCII_12X24[95][48];
GUI_CONST_STORAGE GUI_CHARINFO GUI_FontHZ_CharInfo[8] =
{
{ 8, 8, 1, ( void *)ASCII_08X16},
{ 16, 16, 2, ( void *)HZ_16X16},
{ 12, 12, 2, ( void *)ASCII_12X24},
{ 24, 24, 3, ( void *)HZ_24X24},
};
GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ16_PropHZ = {
0xA1A1,
0xF7FE,
&GUI_FontHZ_CharInfo[1],
(void *)0,
};
GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ16_PropASCII = {
0x0000,
0x007F,
&GUI_FontHZ_CharInfo[0],
(void GUI_CONST_STORAGE *)&GUI_FontHZ16_PropHZ,
};
GUI_CONST_STORAGE GUI_FONT GUI_FontHZ16 =
{
GUI_FONTTYPE_PROP_HZ,
16,
16,
1,
1,
(void GUI_CONST_STORAGE *)&GUI_FontHZ16_PropASCII
};
GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ24_PropHZ = {
0xA1A1,
0xF7FE,
&GUI_FontHZ_CharInfo[3],
(void *)0,
};
GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ24_PropASCII = {
0x0000,
0x007F,
&GUI_FontHZ_CharInfo[2],
(void GUI_CONST_STORAGE *)&GUI_FontHZ24_PropHZ,
};
GUI_CONST_STORAGE GUI_FONT GUI_FontHZ24 =
{
GUI_FONTTYPE_PROP_HZ,
24,
24,
1,
1,
(void GUI_CONST_STORAGE *)&GUI_FontHZ24_PropASCII
};
在GUI_UC_EncodeNone.c文件中填放如下代码:
#include "GUI_Private.h"
static U16 _GetCharCode(const char GUI_UNI_PTR * s)
{
if((*s)>0xA1){
return *(const U16 GUI_UNI_PTR *)s;
}
return *(const U8 GUI_UNI_PTR *)s;
}
static int _GetCharSize(const char GUI_UNI_PTR * s)
{
GUI_USE_PARA(s);
if((*s) >= 0xA1) {
return 2;
}
return 1;
}
static int _CalcSizeOfChar(U16 Char) {
GUI_USE_PARA(Char);
if(Char >= 0xA1A1) {
return 2;
}
return 1;
}
static int _Encode(char *s, U16 Char)
{
if(Char >= 0xA1A1){
*((U16 *)s) = (U16)(Char);
return 2;
}
*s = (U8)(Char);
return 1;
}
const GUI_UC_ENC_APILIST GUI_UC_None = {
_GetCharCode,
_GetCharSize,
_CalcSizeOfChar,
_Encode
};
const GUI_UC_ENC_APILIST GUI__API_TableNone = {
_GetCharCode,
_GetCharSize,
_CalcSizeOfChar,
_Encode
};
void GUI_UC_SetEncodeNone(void)
{
#if GUI_SUPPORT_UNICODE
GUI_LOCK();
GUI_Context.pUC_API = &GUI_UC_None;
GUI_UNLOCK();
#endif
}
在GUICharPEx.c文件中填入如下代码:
#include "GUI_Private.h"
#include "flash.h"
extern const unsigned char ASCII_08X16[95][16];
extern const unsigned char ASCII_12X24[95][48];
//字模数据的暂存数组,以单个字模的最大字节数为设定值
#define BYTES_PER_FONT 48
static U8 GUI_FontDataBuf[BYTES_PER_FONT];
static void GUI_GetDataFromMemory(const GUI_FONT_PROP GUI_UNI_PTR *pProp, U16P c)
{
U8 qh,ql;
U32 foffset;
U32 i;
U16 BytesPerFont;
U8 *asciiaddr;
U8 *baseaddr;
baseaddr = (U8 *)pProp->paCharInfo->pData;
BytesPerFont = GUI_pContext->pAFont->YSize * pProp->paCharInfo->BytesPerLine; //每个字模的数据字节数
if (BytesPerFont > BYTES_PER_FONT) BytesPerFont = BYTES_PER_FONT;
if (c<0x80){ //英文字符地址偏移算法
if (c<0x20){
for(i=0;i GUI_FontDataBuf[i] = 0x00; //ASCII控制字符用黑块表示
}
} else {
asciiaddr = baseaddr + (c-0x20)*BytesPerFont;
for(i=0;i GUI_FontDataBuf[i] = asciiaddr[i]; //调用ASCII字体
}
}
} else {
ql = c/256;
qh = c%256;
if (qh<0xA1||ql<0xA1||ql>0xFE||qh>0xF7){ //非常用汉字
for (i=0;i return; //结束访问
}
ql -= 0xA1;
qh -= 0xA1;
foffset=((unsigned long)94*qh+ql)*BytesPerFont;//得到字库中的字节偏移量
flash_read(GUI_FontDataBuf,foffset+(U32)baseaddr,BytesPerFont);
}
}
void GUIPROP_HZ_DispChar(U16P c)
{
int BytesPerLine;
GUI_DRAWMODE DrawMode = GUI_pContext->TextMode;
const GUI_FONT_PROP GUI_UNI_PTR *pProp = GUI_pContext->pAFont->p.pProp;
for (; pProp; pProp = pProp->pNext){
if ((c >= pProp->First) && (c <= pProp->Last)){
break;
}
}
if (pProp){
GUI_DRAWMODE OldDrawMode;
const GUI_CHARINFO GUI_UNI_PTR * pCharInfo = pProp->paCharInfo;
GUI_GetDataFromMemory(pProp, c);//取出字模数据
BytesPerLine = pCharInfo->BytesPerLine;
OldDrawMode = LCD_SetDrawMode(DrawMode);
LCD_DrawBitmap(GUI_pContext->DispPosX, GUI_pContext->DispPosY,
pCharInfo->XSize, GUI_pContext->pAFont->YSize,
GUI_pContext->pAFont->XMag, GUI_pContext->pAFont->YMag,
1, /* Bits per Pixel */
BytesPerLine,
&GUI_FontDataBuf[0],//&GUI_FontDataBufText[0],//
&LCD_BKCOLORINDEX
);
if (GUI_pContext->pAFont->YDist > GUI_pContext->pAFont->YSize){
int YMag = GUI_pContext->pAFont->YMag;
int YDist = GUI_pContext->pAFont->YDist * YMag;
int YSize = GUI_pContext->pAFont->YSize * YMag;
if (DrawMode != LCD_DRAWMODE_TRANS) {
LCD_COLOR OldColor = GUI_GetColor();
GUI_SetColor(GUI_GetBkColor());
LCD_FillRect(GUI_pContext->DispPosX, GUI_pContext->DispPosY + YSize,
GUI_pContext->DispPosX + pCharInfo->XSize,
GUI_pContext->DispPosY + YDist);
GUI_SetColor(OldColor);
}
}
LCD_SetDrawMode(OldDrawMode); /* Restore draw mode */
GUI_pContext->DispPosX += pCharInfo->XDist * GUI_pContext->pAFont->XMag;
}
}
int GUIPROP_HZ_GetCharDistX(U16P c, int * pSizeX)
{
const GUI_FONT_PROP GUI_UNI_PTR * pProp = GUI_pContext->pAFont->p.pProp;
for (; pProp; pProp = pProp->pNext) {
if ((c >= pProp->First) && (c <= pProp->Last))break;
}
return (pProp) ? (pProp->paCharInfo)->XSize * GUI_pContext->pAFont->XMag : 0;
}
最后,在emWin库的头文件GUI.h的恰当位置,约1750行处添加如下代码:
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ16;
extern GUI_CONST_STORAGE GUI_FONT GUI_FontHZ24;
#define GUI_FONT_HZ16 &GUI_FontHZ16
#define GUI_FONT_HZ24 &GUI_FontHZ24
完成之后,编译一般不会不通过的,通过之后,可写如下小程序测试一下效果:
int main( void )
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); //如果用stmemwin,这条代码必须有
flash_init(); //字库FLASH驱动初始化
GUI_Init();
GUI_Clear();
GUI_DispString("Hello!,草泥马就是羊驼!
");
while (1){
GUI_Delay(100);
}
}
OK!祝你成功!