硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2762|回复: 7
收起左侧

[emWin教程入门篇] 【emWin实战教程V2.0】第25章  全字库在STemWin上的实现(GB2312编码)

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
发表于 2017-1-22 15:35:20 | 显示全部楼层 |阅读模式
完整65章+12章附件教程下载地址:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=19834


第25章      全字库在STemWin上的实现(GB2312编码)



    本章节为大家讲解GB2312编码全字库的实现,对于习惯了GB2312编码的用户来说,使用本章节的方法非常合适。emWin本身是不支持GB2312编码字符显示的,本章节是新创建一种字体类型来实现GB2312编码字符的显示,所采用的方式是早期UCGUI3.98时期遗留下来,但对那种方法进行了修改,以适合高版本emWin5.xx的使用。
    25.1  初学者重要提示
    25.2 GB2312编码全字库说明
    25.3 GB2312全字库的移植方法
    25.4 移植文件简易说明
    25.5 GB2312字库使用方法
    25.6 实验例程说明(RTOS)
    25.7 实验例程说明(裸机)
    25.8 总结



25.1  初学者重要提示

1、对于不习惯前面章节讲解的XBF格式和SIF格式的Unicode编码全字库的用户来说,使用GB2312编码是很好的选择,很适合初学者,汉字操作方式与大家使用裸机代码(没有使用GUI)时是一样的。

2、GB2312编码的全字库文件可以存到任何外部存储介质中。本章节配套例子是将其存储到SPI Flash里面了。

3、使用GB2312编码也是有缺点的,相比前面章节使用FontCvt生成的XBF格式和SIF格式全字库,GB2312编码全字库不支持抗锯齿效果,且仅支持等宽字体(仅支持等宽是因为当前新字体的创建方法不支持非等宽字体)。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-22 15:39:09 | 显示全部楼层
25.2 GB2312编码全字库说明


    本章节配套例子使用的字库是从字库芯片提取出来的,下面是点阵字库相关信息,仅列出了要用到的点阵字符:
25.1.png

了解了点阵字体的相关信息后,剩下就是寻址算法了。

    汉字点阵在汉字库中的地址计算:
    汉字库种类繁多,但都是按照区位的顺序排列的。前一个字节为该汉字的区号,后一个字节为该字的位号,位号是该字在该区中的位置。GB2312编码区范围是A1A1到F7FE,一共F7-A1+1 = 87个区,每区有FE-A1+1=94个字符,因此GB2312可以表示87*94=8178个字符。
    计算公式为:(94 *(区号 - 1) + 位号 - 1) * 一个汉字字模占用字节数
    我们在计算机中常用的汉字编码为汉字内码,不是区位码,需要进行转换。因此最终的计算公式为:
    ADDRESS = [(内码1 - 0xa1)* 94 + (内码2 - 0xa1)] *一个汉字字模占用字节数
    (内码1对应区号,内码2对应位号)
     ASCII区,GB2312编码的全角字符区和汉字区的所有字符可以看下这个帖子:http://www.armbbs.cn/forum.php?mod=viewthread&tid=201 ,初学者务必看下,非常有必要。

下面对这8种点阵依次做下说明:
汉字点阵GB2312编码字库地址计算
    GBCode表示汉字内码。
    MSB 表示汉字内码GBCode的高8bits,
    LSB 表示汉字内码GBCode的低8bits。
    Address 表示汉字或ASCII字符点阵在芯片中的字节地址。
    BaseAdd:说明点阵数据在字库中的起始地址。
11*12点阵计算方法:
    BaseAdd=0x0;  
    if(MSB >=0xA1 && MSB <= 0Xa9 &&LSB >=0xA1)
             Address =((MSB – 0xA1) * 94 + (LSB – 0xA1))*24+BaseAdd;
    else if(MSB >=0xB0 && MSB <= 0xF7&& LSB >=0xA1)
             Address =((MSB – 0xB0) * 94 + (LSB – 0xA1)+ 846)*24+BaseAdd;
15*16点阵计算方法:
    BaseAdd=0x2C9D0;
    if(MSB >=0xA1 && MSB <= 0Xa9 &&LSB >=0xA1)
        Address =( (MSB - 0xA1) * 94 + (LSB - 0xA1))*32+BaseAdd;
    else if(MSB >=0xB0 && MSB <= 0xF7&& LSB >=0xA1)
       Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*32+BaseAdd;
24*24点阵计算方法:
    BaseAdd=0x68190;
    if(MSB >=0xA1 && MSB <= 0Xa9 && LSB >=0xA1)
        Address =( (MSB - 0xA1) * 94 + (LSB - 0xA1))*72+BaseAdd;
    else if(MSB >=0xB0 && MSB <= 0xF7 && LSB >=0xA1)
        Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*72+BaseAdd;
32*32点阵计算方法:
    BaseAdd=0XEDF00;
    if(MSB >=0xA1 && MSB <= 0Xa9 && LSB >=0xA1)
        Address =( (MSB - 0xA1) * 94 + (LSB - 0xA1))*128+BaseAdd;
    else if(MSB >=0xB0 && MSB <= 0xF7 && LSB >=0xA1)
        Address = ((MSB - 0xB0) * 94 + (LSB - 0xA1)+ 846)*128+BaseAdd;
    这四种点阵字体除了每个点阵字符的字节数和起始地址不一样,其余都是一样的。其中第一个if条件语句是判断区号在0xA1到0xA8里面的全角字符区,共846个字符。第二个else if条件语句是判断区号在0xB0到0xF7里面的汉字区,共6763个汉字。
ASCII字符地址计算
     ASCIICode:表示ASCII 码( 8bits)
    BaseAdd:说明该套字库在芯片中的起始地址。
    Address: ASCII字符点阵在芯片中的字节地址。
6x12点阵ASCII计算方法:
    BaseAdd=0x1DBE00
    if (ASCIICode >= 0x20) and (ASCIICode <= 0x7E)
       Address = (ASCIICode –0x20 ) * 12+BaseAdd
8x16点阵ASCII计算方法:
    BaseAdd=0x1DD780
    if (ASCIICode >= 0x20) and (ASCIICode <= 0x7E)
         Address = (ASCIICode –0x20 ) * 16+BaseAdd
12x24点阵ASCII计算方法:
    BaseAdd=0x1DFF00
    if (ASCIICode >= 0x20) and (ASCIICode <= 0x7E)
        Address = (ASCIICode –0x20 ) * 48+BaseAdd
16x32点阵ASCII计算方法:
    BaseAdd=0x1E5A50
    if (ASCIICode >= 0x20) and (ASCIICode <= 0x7E)
      Address = (ASCIICode –0x20 ) * 64+BaseAdd
    这四种点阵字体除了每个点阵字符的字节数和起始地址不一样,其余都是一样的。每个点阵都是只用到了0x200x7E,共96个字符。
    ---------------------------------------------------------------
    讲解完编码地址的计算后,再说一个比较重要的知识点,初学者容易在这个问题上面犯迷糊。汉字内码在文件里面存储的时候就是按照高低字节依次存储的,比如汉字“我”的GB2312编码是0xced2,汉字“们”的编码是0xc3c7,现在我们在电脑端新建一个记事本文件,然后将“我们”这两个字写到电脑端的记事本里面,然后保存,文本编码类型选择ANSI即可。
25.2.png

此时将这个文本文件用winhex打开,可以看到,编码数值如下:
25.3.png

跟汉字的编码值对比后发现汉字的编码值存储就是高低字节依次存储的。那么问题来了,一般情况下,使用MCU微控制器的时候都是用的小端模式,即低地址存储低位数据,高地址存储高位数据。现在我们采用如下的程序做简单的测试:
  1. char *ptr = {"我们"};
  2. U16 c1, c2;
  3.    
  4. c1 = *(U16 *)ptr;
  5. c2 = *(U16 *)(ptr + 2);
  6. printf("c1 = %x, c2 = %x\\r\\n", c1, c2);
复制代码
串口打印的输出结果就是 c1 = 0xd2ce , c2 = 0xc7c3。正好与汉字内码的高低字节反过来了,初学者在学习的时候务必要注意这个问题。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-22 15:42:58 | 显示全部楼层
25.3   GB2312全字库的移植方法

    这里用到的几个移植文件是早期UCGUI3.XX版本时代遗留下来的,但都进行了修改,更加适合STemWin5.xx版本使用(由于早期UCGUI3.XX版本是有源码的,这种方式是在源码的基础上新创建的一种字体方式,适合国内用的GB编码)。
25.4.png
图25-1

    GUI_Font12.c,GUI_Font16.c,GUI_Font24.c和GUI_Font32.c都是相同的代码结构,仅仅是定义的点阵大小不同,用户要实现其它点阵大小的字体,只需根据这几个文件照葫芦画瓢即可。剩下的两个文件GUI_UC_EncondeNone.c和GUICharPEx.c是必须要包含的,用户需要根据字库的起始位置做修改(如何修改,看本章节的25.4小节,本章节配套的例子不用改,因为已经根据25.2小节的起始地址设置好了)。
    接下来要做的移植工作比较简单,仅需两步即可完成:
第1步:将图25-1中的6个文件全部添加到工程中,IAR和MDK是一样的,下面以MDK为例进行说明。
25.5.png


    上面的截图就是添加到MDK工程的效果。如果用户要移植这几个文件到自己的工程项目,直接从本章节配套例子的emWin文件夹下打开文件HanZi就看到这几个文件了,所以用户只需复制粘贴HanZi到自己的工程项目即可。
第2步:在GUI_Type.h文件添加一种新的字体类型定义
    新添加的字体类型如下:
        DECLARE_FONT(USER);
        #define GUI_FONTTYPE_USER       \\
                GUIUSER_DispChar,         \\
                GUIUSER_GetCharDistX,    \\
                GUIMONO_GetFontInfo,    \\
                GUIMONO_IsInFont,        \\
                (GUI_GETCHARINFO *)0,    \\
                (tGUI_ENC_APIList*)0
    此定义放在等宽字体定义的前面即可:
25.6.png

    通过这两步就完成移植了,剩下就是如何使用了。不过第2步里面新添加的函数有必要简单的解释一下。
首先是函数DECLARE_FONT(USER),这个函数的原始定义如下:
  1. #define DECLARE_FONT(Type)                                     \\
  2. void GUI##Type##_DispChar    (U16P c);                         \\
  3. int  GUI##Type##_GetCharDistX(U16P c, int * pSizeX);                       \\
  4. void GUI##Type##_GetFontInfo (const GUI_FONT * pFont, GUI_FONTINFO * pfi); \\
  5. char GUI##Type##_IsInFont    (const GUI_FONT * pFont, U16 c); \\
  6. int  GUI##Type##_GetCharInfo (U16P c, GUI_CHARINFO_EXT * pInfo)
复制代码
##是预处理运算符,这种方式有效的对宏定义进行了扩展,DECLARE_FONT里面的参数是可以任意定义的,只要满足函数命名即可,比如用户调用了DECLARE_FONT(USER),就相当于一次声明了5个函数:
  1. void GUIUSER_DispChar    (U16P c);                         \\
  2. int  GUIUSER _GetCharDistX(U16P c, int * pSizeX);                       \\
  3. void GUIUSER _GetFontInfo (const GUI_FONT * pFont, GUI_FONTINFO * pfi); \\
  4. char GUIUSER _IsInFont    (const GUI_FONT * pFont, U16 c); \\
  5. int  GUIUSER _GetCharInfo (U16P c, GUI_CHARINFO_EXT * pInfo)
复制代码
也就是将Type前后的预处理运算符##去掉,并将Type用USER代替。在GUI_Type.h文件里面还有其它几种字体类型的定义,都是这个意思。
  1. DECLARE_FONT(MONO);
  2. DECLARE_FONT(PROP);
  3. DECLARE_FONT(PROP_EXT);
  4. DECLARE_FONT(PROP_FRM);
  5. DECLARE_FONT(PROPAA);
  6. DECLARE_FONT(PROP_AA2);
  7. DECLARE_FONT(PROP_AA2_EXT);
  8. DECLARE_FONT(PROP_AA4);
  9. DECLARE_FONT(PROP_AA4_EXT);
  10. DECLARE_FONT(USER);
复制代码
再说下宏定义#define GUI_FONTTYPE_USER
    这种形式的宏定义也很少见,宏定义后面跟了好几个子函数。其实就是一种简单的替换,在程序代码遇到GUI_FONTTYPE_USER的地方,就用下面的代替
         GUIUSER_DispChar,         \\
         GUIUSER_GetCharDistX,    \\
         GUIMONO_GetFontInfo,    \\
         GUIMONO_IsInFont,        \\
         (GUI_GETCHARINFO *)0,    \\
         (tGUI_ENC_APIList*)0
    此宏定义是在文件GUI_Font12.c,GUI_Font16.c,GUI_Font24.c和GUI_Font32.c里面被调用。关于替代的这几个函数有必要再进一步的阐释下。
    函数GUIUSER_DispChar和GUIUSER_GetCharDistX是要用户自己实现的,已经在GUICharPEx.c里面实现了。函数GUIUSER_GetFontInfo和GUIUSER_IsInFont没有实现,而是用emWin等宽字体的GUIMONO_GetFontInfo和GUIMONO_IsInFont实现的。剩下的两个函数(GUI_GETCHARINFO *)0和(tGUI_ENC_APIList*)0未做实现,使用emWin自带的方式来实现。讲解到这里,初学者会有疑问,为什么字体类型要定义这几种函数?其实这个是由emWin的字体类型变量决定的,定义如下:
  1. struct GUI_FONT {
  2.   GUI_DISPCHAR     * pfDispChar;
  3.   GUI_GETCHARDISTX * pfGetCharDistX;
  4.   GUI_GETFONTINFO  * pfGetFontInfo;
  5.   GUI_ISINFONT     * pfIsInFont;
  6.   GUI_GETCHARINFO  * pfGetCharInfo;
  7.   const tGUI_ENC_APIList* pafEncode;
  8.   U8 YSize;
  9.   U8 YDist;
  10.   U8 XMag;
  11.   U8 YMag;
  12.   union {
  13.     const void              * pFontData;
  14.     const GUI_FONT_MONO     * pMono;
  15.     const GUI_FONT_PROP     * pProp;
  16.     const GUI_FONT_PROP_EXT * pPropExt;
  17.   } p;
  18.   U8 Baseline;
  19.   U8 LHeight;     /* Height of a small lower case character (a,x) */
  20.   U8 CHeight;     /* Height of a small upper case character (A,X) */
  21. };
复制代码
    结构体GUI_FONT前六个成员就是我们这里实现的,其余的几种字体类型全是如此:
  1. DECLARE_FONT(MONO);
  2. DECLARE_FONT(PROP);
  3. DECLARE_FONT(PROP_EXT);
  4. DECLARE_FONT(PROP_FRM);
  5. DECLARE_FONT(PROPAA);
  6. DECLARE_FONT(PROP_AA2);
  7. DECLARE_FONT(PROP_AA2_EXT);
  8. DECLARE_FONT(PROP_AA4);
  9. DECLARE_FONT(PROP_AA4_EXT);
  10. /* MONO: Monospaced fonts */
  11. #define GUI_FONTTYPE_MONO       \\
  12.   GUIMONO_DispChar,             \\
  13.   GUIMONO_GetCharDistX,         \\
  14.   GUIMONO_GetFontInfo,          \\
  15.   GUIMONO_IsInFont,             \\
  16.   (GUI_GETCHARINFO *)0,         \\
  17.   (tGUI_ENC_APIList*)0
  18. /* PROP: Proportional fonts */
  19. #define GUI_FONTTYPE_PROP       \\
  20.   GUIPROP_DispChar,             \\
  21.   GUIPROP_GetCharDistX,         \\
  22.   GUIPROP_GetFontInfo,          \\
  23.   GUIPROP_IsInFont,             \\
  24.   (GUI_GETCHARINFO *)0,         \\
  25.   (tGUI_ENC_APIList*)0
  26. /* PROP_EXT: Extended proportional fonts */
  27. #define GUI_FONTTYPE_PROP_EXT       \\
  28.   GUIPROP_EXT_DispChar,             \\
  29.   GUIPROP_EXT_GetCharDistX,         \\
  30.   GUIPROP_EXT_GetFontInfo,          \\
  31.   GUIPROP_EXT_IsInFont,             \\
  32.   GUIPROP_EXT_GetCharInfo,          \\
  33.   &GUI_ENC_APIList_EXT
  34. /* PROP_FRM: Extended proportional fonts, framed */
  35. #define GUI_FONTTYPE_PROP_FRM       \\
  36.   GUIPROP_FRM_DispChar,             \\
  37.   GUIPROP_FRM_GetCharDistX,         \\
  38.   GUIPROP_FRM_GetFontInfo,          \\
  39.   GUIPROP_FRM_IsInFont,             \\
  40.   (GUI_GETCHARINFO *)0,             \\
  41.   (tGUI_ENC_APIList*)0
  42. /* PROP: Proportional fonts SJIS */
  43. #define GUI_FONTTYPE_PROP_SJIS  \\
  44.   GUIPROP_DispChar,             \\
  45.   GUIPROP_GetCharDistX,         \\
  46.   GUIPROP_GetFontInfo,          \\
  47.   GUIPROP_IsInFont,             \\
  48.   (GUI_GETCHARINFO *)0,         \\
  49.   &GUI_ENC_APIList_SJIS
  50. /* PROPAA: Proportional, antialiased fonts */
  51. #define GUI_FONTTYPE_PROPAA       \\
  52.   GUIPROPAA_DispChar,             \\
  53.   GUIPROPAA_GetCharDistX,         \\
  54.   GUIPROPAA_GetFontInfo,          \\
  55.   GUIPROPAA_IsInFont,             \\
  56.   (GUI_GETCHARINFO *)0,           \\
  57.   (tGUI_ENC_APIList*)0
  58. /* PROP_AA2: Proportional, antialiased fonts, 2bpp */
  59. #define GUI_FONTTYPE_PROP_AA2       \\
  60.   GUIPROP_AA2_DispChar,             \\
  61.   GUIPROP_AA2_GetCharDistX,         \\
  62.   GUIPROP_AA2_GetFontInfo,          \\
  63.   GUIPROP_AA2_IsInFont,             \\
  64.   (GUI_GETCHARINFO *)0,             \\
  65.   (tGUI_ENC_APIList*)0
  66. /* PROP_AA2_EXT: Proportional, antialiased fonts, 2bpp, extended font information */
  67. #define GUI_FONTTYPE_PROP_AA2_EXT   \\
  68.   GUIPROP_AA2_EXT_DispChar,         \\
  69.   GUIPROP_EXT_GetCharDistX,         \\
  70.   GUIPROP_EXT_GetFontInfo,          \\
  71.   GUIPROP_EXT_IsInFont,             \\
  72.   GUIPROP_EXT_GetCharInfo,          \\
  73.   &GUI_ENC_APIList_EXT
  74. /* PROP_AA2: Proportional, antialiased fonts, 2bpp, SJIS encoding */
  75. #define GUI_FONTTYPE_PROP_AA2_SJIS  \\
  76.   GUIPROP_AA2_DispChar,             \\
  77.   GUIPROP_AA2_GetCharDistX,         \\
  78.   GUIPROP_AA2_GetFontInfo,          \\
  79.   GUIPROP_AA2_IsInFont,             \\
  80.   (GUI_GETCHARINFO *)0,             \\
  81.   &GUI_ENC_APIList_SJIS
  82. /* PROP_AA4: Proportional, antialiased fonts, 4bpp */
  83. #define GUI_FONTTYPE_PROP_AA4       \\
  84.   GUIPROP_AA4_DispChar,             \\
  85.   GUIPROP_AA4_GetCharDistX,         \\
  86.   GUIPROP_AA4_GetFontInfo,          \\
  87.   GUIPROP_AA4_IsInFont,             \\
  88.   (GUI_GETCHARINFO *)0,             \\
  89.   (tGUI_ENC_APIList*)0
  90. /* PROP_AA4_EXT: Proportional, antialiased fonts, 4bpp, extended font information */
  91. #define GUI_FONTTYPE_PROP_AA4_EXT   \\
  92.   GUIPROP_AA4_EXT_DispChar,         \\
  93.   GUIPROP_EXT_GetCharDistX,         \\
  94.   GUIPROP_EXT_GetFontInfo,          \\
  95.   GUIPROP_EXT_IsInFont,             \\
  96.   GUIPROP_EXT_GetCharInfo,          \\
  97.   &GUI_ENC_APIList_EXT
  98. /* PROP_AA4: Proportional, antialiased fonts, 4bpp, SJIS encoding */
  99. #define GUI_FONTTYPE_PROP_AA4_SJIS  \\
  100.   GUIPROP_AA4_DispChar,             \\
  101.   GUIPROP_AA4_GetCharDistX,         \\
  102.   GUIPROP_AA4_GetFontInfo,          \\
  103.   GUIPROP_AA4_IsInFont,             \\
  104.   (GUI_GETCHARINFO *)0,             \\
  105.   &GUI_ENC_APIList_SJIS
复制代码
关于移植部分就给大家讲解这么多,下面对这几个移植的文件简单的说说。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-22 15:46:09 | 显示全部楼层
25.4移植文件简易说明



25.4.1   文件GUICharPEx.c

    此文件主要是实现了新定义字体里面的API函数GUIUSER_DispChar和GUIUSER_GetCharDistX,其实这两个函数是由UCGUI3.98源码里面的文件GUICharP.c修改而来。关于这两个函数暂不做讲解,用户使用的时候也不需要对这两个函数做修改,接下来重点看函数:
          static voidGUI_GetDataFromMemory(const GUI_FONT_PROP GUI_UNI_PTR *pProp, U16P c)
的实现,这个函数是需要用户去实现的,根据使用的外部存储器和汉字库地址实现点阵数据的读取。下面是根据25.2小节的说明,实现从SPI Flash里面读取点阵数据:
  1. /* 点阵数据缓存, 必须大于等于单个字模需要的存储空间 */
  2. #define BYTES_PER_FONT      512
  3. static U8 GUI_FontDataBuf[BYTES_PER_FONT];
  4. /*
  5. *********************************************************************************************************
  6. *    函 数 名: GUI_GetDataFromMemory
  7. *    功能说明: 读取点阵数据
  8. *    形    参: pProp  GUI_FONT_PROP类型结构
  9. *             c      字符
  10. *    返 回 值: 无
  11. *********************************************************************************************************
  12. */
  13. static void GUI_GetDataFromMemory(const GUI_FONT_PROP GUI_UNI_PTR *pProp, U16P c)
  14. {
  15.     U16 BytesPerFont;
  16.     U32 oft = 0, BaseAdd;
  17. U8 code1,code2;
  18.    
  19.      char *font = (char *)pProp->paCharInfo->pData;
  20.      /* 每个字模的数据字节数 */
  21.     BytesPerFont = GUI_pContext->pAFont->YSize * pProp->paCharInfo->BytesPerLine;
  22.     if (BytesPerFont > BYTES_PER_FONT)
  23.      {
  24.          BytesPerFont = BYTES_PER_FONT;
  25.      }
  26.    
  27.      /* 英文字符地址偏移计算 */
  28.     if (c < 0x80)                                                               
  29.     {
  30.          if(strncmp("A12", font, 3) == 0)     /* 6*12 ASCII字符 */
  31.          {
  32.               BaseAdd = 0x1DBE00;
  33.          }
  34.          else if(strncmp("A16", font, 3) == 0) /* 8*16 ASCII字符 */
  35.          {
  36.               BaseAdd = 0x1DD780;
  37.          }
  38.          else if(strncmp("A24", font, 3) == 0) /* 12*24 ASCII字符 */
  39.          {
  40.               BaseAdd = 0x1DFF00;
  41.          }
  42.          else if(strncmp("A32", font, 3) == 0) /* 24*48 ASCII字符 */
  43.          {
  44.               BaseAdd = 0x1E5A50;
  45.          }
  46.         
  47.          oft = (c-0x20) * BytesPerFont + BaseAdd;
  48.     }
  49.      /* 汉字和全角字符的偏移地址计算 */
  50.     else                                                                          
  51.     {
  52.          if(strncmp("H12", font, 3) == 0)      /* 12*12 字符 */
  53.          {
  54.               BaseAdd = 0x0;
  55.          }
  56.          else if(strncmp("H16", font, 3) == 0)  /* 16*16 字符 */
  57.          {
  58.               BaseAdd = 0x2C9D0;
  59.          }
  60.          else if(strncmp("H24", font, 3) == 0)  /* 24*24 字符 */
  61.          {
  62.               BaseAdd = 0x68190;
  63.          }
  64.          else if(strncmp("H32", font, 3) == 0)  /* 32*32 字符 */
  65.          {
  66.               BaseAdd = 0XEDF00;
  67.          }
  68.         
  69.          /* 根据汉字内码的计算公式锁定起始地址 */
  70.          code2 = c >> 8;
  71.          code1 = c & 0xFF;
  72.          if (code1 >=0xA1 && code1 <= 0xA9 && code2 >=0xA1)
  73.          {
  74.               oft = ((code1 - 0xA1) * 94 + (code2 - 0xA1)) * BytesPerFont + BaseAdd;
  75.          }
  76.          else if (code1 >=0xB0 && code1 <= 0xF7 && code2 >=0xA1)
  77.          {
  78.               oft = ((code1 - 0xB0) * 94 + (code2 - 0xA1) + 846) * BytesPerFont + BaseAdd;
  79.          }
  80.     }
  81.    
  82.      /* 读取点阵数据 */
  83.      sf_ReadBuffer(GUI_FontDataBuf, oft, BytesPerFont);
  84. }
复制代码

汉字和ASCII点阵数据的起始地址计算公式就是前面25.2小节讲解的内容,只是都合并成一个公式来实现了。

25.4.2   文件GUI_UC_EncodeNone.c


    这个文件就是来自UCGUI3.98源码,并对其进行了简单修改,以适合我们的GB2312编码,特别注意一点,在emWin的源码里面也是有一个此文件的,添加了这个文件,会把原有的文件覆盖掉。
  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) /* ASCII字符编码是00-7F,返回一个字节数据即可,GB2312编码是A1A1到FEFE,需要返回两个字节
  17. 数据,这里以第一个字节作为判断即可 */
  18.   {
  19.     return *(const U16 GUI_UNI_PTR *)s;
  20.   }
  21.   return *(const U8 GUI_UNI_PTR *)s;
  22. }
  23. /*********************************************************************
  24. *
  25. *       _GetCharSize
  26. *
  27. * Purpose:
  28. *   Return the number of bytes of the current character.
  29. */
  30. static int _GetCharSize(const char GUI_UNI_PTR * s) {
  31.   GUI_USE_PARA(s);
  32. if((*s) > 0xA0) /* ASCII字符编码是00-7F,返回一个字节大小,GB2312编码是A1A1到FEFE,需要返回两个字节大小,
  33. 这里以第一个字节作为判断即可 */
  34.   {
  35.     return 2;
  36.   }
  37.   return 1;
  38. }
  39. /*********************************************************************
  40. *
  41. *       _CalcSizeOfChar
  42. *
  43. * Purpose:
  44. *   Return the number of bytes needed for the given character.
  45. */
  46. static int _CalcSizeOfChar(U16 Char) {
  47.   GUI_USE_PARA(Char);
  48.   if(Char > 0xA0A0) /* ASCII字符编码是00-7F,返回一个字节大小,GB2312编码是A1A1到FEFE,需要返回两个字节大
  49. 小,这里以A0A0作为判断*/
  50.   {
  51.     return 2;
  52.   }
  53.   return 1;
  54. }
  55. /*********************************************************************
  56. *
  57. *       _Encode
  58. *
  59. * Purpose:
  60. *   Encode character into 1/2/3 bytes.
  61. */
  62. static int _Encode(char *s, U16 Char) {
  63.   if(Char > 0xA0A0) /* ASCII字符编码是00-7F,返回一个字节大小,GB2312编码是A1A1到FEFE,需要返回两个字节大
  64. 小,这里以A0A0作为判断,并将编码中赋值给形参s */
  65.   {
  66.     *((U16 *)s) = (U16)(Char);
  67.     return 2;
  68.   }
  69.   *s = (U8)(Char);
  70.   return 1;
  71. }
  72. /*********************************************************************
  73. *
  74. *       Static data
  75. *
  76. **********************************************************************
  77. */
  78. /*********************************************************************
  79. *
  80. *       _API_Table
  81. */
  82. const GUI_UC_ENC_APILIST GUI__API_TableNone = {
  83.   _GetCharCode,     /*  return character code as U16 */
  84.   _GetCharSize,     /*  return size of character: 1 */
  85.   _CalcSizeOfChar,  /*  return size of character: 1 */
  86.   _Encode           /*  Encode character */
  87. };
  88. const GUI_UC_ENC_APILIST GUI_UC_None = {
  89.   _GetCharCode,     /*  return character code as U16 */
  90.   _GetCharSize,     /*  return size of character: 1 */
  91.   _CalcSizeOfChar,  /*  return size of character: 1 */
  92.   _Encode           /*  Encode character */
  93. };
复制代码

25.4.3   文件GUI_Font12.c,GUI_Font16.c等


    这几个文件都是同一个架构,我们这里以GUI_Font16.c文件为例进行说明。
  1. #include "GUI.h"
  2. #include "GUI_Type.h"
  3. GUI_CONST_STORAGE GUI_CHARINFO GUI_FontHZ16_CharInfo[2] =  // ----------(1)
  4. {   
  5.     {  8,    8,  1, (void *)"A16"},     
  6.     {  16,  16,  2, (void *)"H16"},         
  7. };
  8. GUI_CONST_STORAGE GUI_FONT_PROP GUI_FontHZ16_PropHZ= {   // ----------(2)
  9.       0xA1A1,
  10.       0xFEFE,
  11.       &GUI_FontHZ16_CharInfo[1],
  12.       (void *)0,
  13. };
  14. GUI_CONST_STORAGE  GUI_FONT_PROP GUI_FontHZ16_PropASC= {  // ----------(3)
  15.       0x0000,
  16.       0x007F,
  17.       &GUI_FontHZ16_CharInfo[0],
  18.       (void GUI_CONST_STORAGE *)&GUI_FontHZ16_PropHZ,
  19. };
  20. GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ16 =              // ----------(4)
  21. {
  22.        GUI_FONTTYPE_USER,
  23.       16,
  24.       16,
  25.       1,  
  26.       1,  
  27.       (void GUI_CONST_STORAGE *)&GUI_FontHZ16_PropASC,
  28. };
  29. GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ16x2 =            // ----------(5)
  30. {
  31.        GUI_FONTTYPE_USER,
  32.       16,
  33.       16,
  34.       2,  
  35.       2,  
  36.       (void GUI_CONST_STORAGE *)&GUI_FontHZ16_PropASC
  37. };
复制代码
第1个语句:GUI_CONST_STORAGEGUI_CHARINFO GUI_FontHZ16_CharInfo[2]
     了解这个函数得了解GUI_CHARINFO的定义,定义如下:
  1. typedef struct {
  2.   U8 XSize;
  3.   U8 XDist;
  4.   U8 BytesPerLine;
  5.   const unsigned char * pData;
  6. } GUI_CHARINFO;
复制代码
第1个成员U8 Xsize是点阵字符的X轴方向的长度。
第2个成员U8 XDist是实际显示时X轴方向的长度。
第3个成员U8 BytesPerLine是每行点阵数据需要的字节数。
第4个成员const unsigned char *pData用来做一些字符标记。
认识这几个变量成员后,如下两个变量成员也就不难理解了:
{  8, 8,  1, (void *)"A16"}
表示此点阵字符的X轴长度是8个像素点,实际显示也是8个像素点,显示一行需要1个字节就行,用字符A16作为识别标志,这一行的整体作用是用来识别16点阵ASCII。
{  16, 16,  2, (void *)"H16"}
表示此点阵字符的X轴长度是16个像素点,实际显示也是16个像素点,显示一行需要2个字节就行,用字符H16作为识别标志,这一行的整体作用是用来识别16点阵汉字。
第2个语句:GUI_CONST_STORAGEGUI_FONT_PROP GUI_FontHZ16_PropHZ
    了解这个函数得了解GUI_FONT_PROP的定义,定义如下:
  1. typedef struct GUI_FONT_PROP {
  2.   U16P First;                                  /* First character               */
  3.   U16P Last;                                   /* Last character                */
  4.   const GUI_CHARINFO         * paCharInfo;     /* Address of first character    */
  5.   const struct GUI_FONT_PROP * pNext;          /* Pointer to next               */
  6. } GUI_FONT_PROP;
复制代码
第1个成员U16P First是第一个字符的编码值。
第2个成员U16P First是最后一个字符的编码值。
第3个成员const GUI_CHARINFO  *paCharInfo记录了第一个字符的存储位置。
第4个成员const struct GUI_FONT_PROP * pNext用来指向下一个GUI_FONT_PROP定义的字符区间。
对结构体GUI_FONT_PROP的定义了解后,这里定义的如下四个参数:
0xA1A1,  
0xFEFE,  
&GUI_FontHZ16_CharInfo[1],
(void *)0,  
表示此编码区的字符是从0XA1A1开始到0XFEFE。字符的位置由GUI_FontHZ16_CharInfo[1]记录,没有指向下一个编码范围。这里的编码就是GB2312的编码范围。
第3个语句:GUI_CONST_STORAGEGUI_FONT_PROP GUI_FontHZ16_PropASC
    有了上面第二句的解释,第三句也比较好理解了。
这里表示此编码区的字符是从0x0000开始到0x007F。字符的位置由GUI_FontHZ16_CharInfo[0]记录,指向下一个编码范围就是第二句的GB2312编码区。这里的编码就是ASCII的编码范围。
第4个语句:GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ16
    此句就是根据前面25.3小节末尾新创建字体类型所定义的一个16点阵字体。
  1. GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ16 =
  2. {
  3. GUI_FONTTYPE_USER,     /* 表示新定义的字体类型 */
  4. 16,                    /* 字体Y轴方向的点阵高度 */
  5. 16,                    /* 字体Y轴方向的实际显示点阵高度 */
  6. 1,                     /* 字体X轴方向放大到1倍,就是原始大小 */
  7. 1,                     /* 字体Y轴方向放大到1倍 ,就是原始大小 */
  8. (void GUI_CONST_STORAGE*)&GUI_FontHZ16_PropASC,/* 此字体类型从GUI_FontHZ16_PropASC */
  9. };
复制代码
第5个语句:GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ16x2
    跟第4句一样,区别的地方就是将字体放大了1倍。
  1. GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ16 =
  2. {
  3. GUI_FONTTYPE_USER,     /* 表示新定义的字体类型 */
  4. 16,                    /* 字体Y轴方向的点阵高度 */
  5. 16,                    /* 字体Y轴方向的实际显示点阵高度 */
  6. 2,                     /* 字体X轴方向放大到2倍 */
  7. 2,                     /* 字体Y轴方向放大到2倍 */
  8. (void GUI_CONST_STORAGE*)&GUI_FontHZ16_PropASC,/* 此字体类型从GUI_FontHZ16_PropASC */
  9. };
复制代码
关于这个几个移植文件就跟大家讲解这么多。这个就是GUI_Font16.C的讲解,其它的GUI_Font12.c, GUI_Font24.c和GUI_Font32.c是一样的。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-22 15:47:31 | 显示全部楼层
25.5  GB2312字库使用方法


    移植好之后,使用就比较容易了下面分3步进行说明
第1步:声明12点阵,16点阵,24点阵和32点阵的字体,放在了MainTask.h文件里面,方便调用,程序代码中只需包含这个头文件就可以了。
  1. /*
  2. *********************************************************************************************************
  3. *                                         字体声明
  4. *********************************************************************************************************
  5. */
  6. extern GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ32;
  7. extern GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ24;
  8. extern GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ16;
  9. extern GUI_CONST_STORAGE  GUI_FONT GUI_FontHZ12;
复制代码
有几种点阵字库就通过extern声明几个,方便外部文件调用。
第2步:将字库文件font.bin存储到SPI Flash中,我们这里在电脑端将font.bin文件存储到SD卡中(字库文件font.bin已经放在本章节配例子的Doc文件夹),然后开发板上电后将其从SD卡中加载到SPI Flash里面,加载代码如下:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: LoadFontLib()
  4. *    功能说明: 从SD卡中加载字库文件到SPI FLASH
  5. *    形    参: 无      
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void LoadFontLib(void)
  10. {
  11.      float FinishPecent;
  12.     uint32_t Count = 0;
  13.      uint16_t y, i;
  14.      uint8_t ucState;
  15.      char cDispBuf[80];
  16.    
  17.      /* 清屏 */
  18.      GUI_SetBkColor(GUI_BLUE);
  19.      GUI_Clear();
  20.    
  21.      /* 设置字体 */
  22.      GUI_SetFont(GUI_FONT_20_1);
  23.     y = 0;
  24.      /* 第1步:显示操作说明 ***************************************************************/
  25.      GUI_DispStringAt("SPI Flash Chinese character Lab", 0, y);
  26.      y += 20;
  27.    
  28.      GUI_DispStringAt("1. Please make sure the font.bin is saved in SD", 0, y);
  29.      y += 20;
  30.    
  31.      GUI_DispStringAt("2. if the font.bin is not saved in SD, this lab will fail", 0, y);
  32.      y += 20;
  33.    
  34.      /* 等待10s后开始进行复制,方便客户看屏幕上的显示信息 */
  35.      for(i = 0; i < 11; i++)
  36.      {
  37.          sprintf(cDispBuf, "3. 10 seconds will start, %ds..  ", 10 - i);
  38.          GUI_DispStringAt(cDispBuf, 0, y);
  39.          GUI_Delay(1000);
  40.      }
  41.      y += 20;
  42.    
  43.    
  44.      /* 第2步:打开文件 ***************************************************************/
  45.      result = f_open(&file, "font.bin", FA_OPEN_EXISTING | FA_READ);
  46.      if (result !=  FR_OK)
  47.      {
  48.          GUI_DispStringAt("font.bin open failed", 0, y);
  49.          y += 20;
  50.      }
  51.      /* 第3步:复制SD卡中字库文件font.bin到SPI FLASH **********************************/
  52.      for(;;)
  53.      {
  54.          /* 读取一个扇区的数据到buf */
  55.          result = f_read(&file, &tempbuf, g_tSF.PageSize, &bw);
  56.         
  57.          /* 读取出错或者读取完毕,退出 */
  58.          if ((result != FR_OK)||bw == 0)
  59.          {
  60.               break;
  61.          }
  62.         
  63.          /* 写数据到SPI FLASH */
  64.          ucState = sf_WriteBuffer(tempbuf, Count*g_tSF.PageSize, g_tSF.PageSize);
  65.         
  66.          /* 如果返回0,表示复制失败 */
  67.          if(ucState == 0)
  68.          {
  69.               GUI_DispStringAt("copy failed                  ", 0, y);
  70.               break;
  71.          }
  72.         
  73.          /* 显示复制进度 */
  74.          Count = Count + 1;
  75.          FinishPecent = (float)(Count* g_tSF.PageSize) / file.fsize;
  76.          sprintf(cDispBuf, "copying:%02d%%", (uint8_t)(FinishPecent*100));
  77.          GUI_DispStringAt(cDispBuf, 0, y);
  78.      }
  79.    
  80.      /* 等待1秒后开始进去emWin主界面 */
  81.      GUI_Delay(1000);
  82. }
复制代码
第3步:加载到SPI Flash后,使用就很方便了。
    比如设置按钮的字体使用16点阵,调用如下设置函数即可。
    BUTTON_SetFont(hWin, &GUI_FontHZ16);  /* hWin是按钮的句柄 */
    设置其它控件是一样的。另外注意,使用GB编码没有烦人的文件编码设置问题了,从这一点来说,比使用前面章节讲的XBF格式和SIF格式的Unicode编码方便很多了。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-22 15:52:45 | 显示全部楼层
25.6   实验例程说明(RTOS)


配套例子:
    V6-532_STemWin实验_全字库实现,GB2312编码(RTOS)
实验目的:
    1.     学习emWin的GB2312编码全字库的使用方法。
    2.     emWin功能的实现在MainTask.c文件里面。
实验内容:
    1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
    2.     K2按键按下,实现截图功能,将图片以BMP格式保存到SD卡中。
    3.     各个任务实现的功能如下:
              App Task Start   任务:实现按键和触摸扫描。
              App Task MspPro任务 :实现截图功能,将图片以BMP格式保存到SD卡中。
              App Task UserIF  任务:按键消息处理。
              App Task COM   任务:暂未使用。
        App Task GUI    任务:GUI任务。
支持点阵:
    1.     支持12点阵,16点阵,24点阵以及32点阵汉字。
    2.     6X12点阵的ASCII,8X16点阵的ASCII,12X24点阵的ASCII,16X32点阵的ASCII
字库存储方式:
    1.     字库存储到SPI FLASH里面。
实验步骤:
    1.     将字库文件font.bin放到SD卡根目录中,系统上电后会将其加载到SPI FLASH里面。
    2.     板子上电后会有一个加载进度指示,存储到SPI FLASH成功后会显示一个对话框。
实验注意:
    1.     实验所需的字库文件font.bin已经存储到本工程的Doc文件夹下,使用此例子前,请务必将这个文件存储到SD卡根目录中,并将SD卡插到开发板上面。
μCOS-III任务调试信息(按K1按键,串口打印):
25.7.png

STemWin界面显示效果:
    800*480分辨率界面效果。
25.8.png

STemWin动态内存配置:
    GUIConf.c文件中的配置如下:
  1. #define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
  2. #if EX_SRAM
  3. #define GUI_NUMBYTES  (1024*1024*8)
  4. #else
  5. #define GUI_NUMBYTES  (100*1024)
  6. #endif
复制代码
    通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:
#define EX_SRAM    1 表示使用外部SDRAM作为emWin动态内存,大小8MB。
#define EX_SRAM    0 表示使用内部SRAM作为emWin动态内存,大小100KB。
默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。
STemWin底层接口配置:
    LCDConf_Lin_Template.c文件中共12项emWin配置:
  1. /*
  2. **********************************************************************************************************
  3.                                           用户可以配置的选项
  4. **********************************************************************************************************
  5. */
  6. /* 0. 在官方代码的基础上再做优化,官方的部分函数效率低,耗内存, 0表示优化 */
  7. #define emWin_Optimize   0
  8. /*
  9.   1. 显示屏的物理分辨率,驱动已经做了显示屏自适应,支持4.3寸,5寸和7寸屏
  10.      这里填写自适应显示屏中的最大分辨率。
  11. */
  12. #define XSIZE_PHYS       800
  13. #define YSIZE_PHYS       480
  14. /* 2. 多缓冲 / 虚拟屏,多缓冲和虚拟屏不可同时使用,emWin不支持 */
  15. #define NUM_BUFFERS      3 /* 定义多缓冲个数,仅可以设置1,2和3,也就是最大支持三缓冲 */
  16. #define NUM_VSCREENS     1 /* 定义虚拟屏个数 */
  17. /* 3. 没有图层激活时,背景色设置, 暂时未用到 */
  18. #define BK_COLOR         GUI_DARKBLUE
  19. /*
  20.    4. 重定义图层数,对于STM32F429/439,用户可以选择一个图层或者两个图层,不支持三图层
  21.       (1). 设置GUI_NUM_LAYERS = 1时,即仅使用图层1时,默认触摸值是发送给图层1的。
  22.        (2). 设置GUI_NUM_LAYERS = 2时,即图层1和图层2都已经使能,此时图层2是顶层,
  23.             用户需要根据自己的使用情况设置如下两个地方。
  24.             a. 在bsp_touch.c文件中的函数TOUCH_InitHard里面设置参数State.Layer = 1,1就表示
  25.                给图层2发送触摸值。
  26.             b. 调用GUI_Init函数后,调用函数GUI_SelectLayer(1), 设置当前操作的是图层2。
  27. */
  28. #undef  GUI_NUM_LAYERS
  29. #define GUI_NUM_LAYERS    1
  30. /*
  31.    5. 设置图层1和图层2对应的显存地址
  32.       (1) EXT_SDRAM_ADDR 是SDRAM的首地址。
  33.       (2) LCD_LAYER0_FRAME_BUFFER 是图层1的显存地址。
  34.        (3) LCD_LAYER1_FRAME_BUFFER 是图层2的显存地址。
  35.        (4) 每个图层的显存大小比较考究,这里进行下简单的说明。
  36.            如果用户选择的颜色模式 = 32位色ARGB8888,显存的大小:
  37.            XSIZE_PHYS * YSIZE_PHYS * 4 * NUM_VSCREENS * NUM_BUFFERS
  38.          
  39.            颜色模式 = 24位色RGB888,显存的大小:
  40.            XSIZE_PHYS * YSIZE_PHYS * 3 * NUM_VSCREENS * NUM_BUFFERS
  41.          
  42.            颜色模式 = 16位色RGB566,ARGB1555, ARGB4444,AL88,那么显存的大小就是:
  43.            XSIZE_PHYS * YSIZE_PHYS * 2 * NUM_VSCREENS * NUM_BUFFERS
  44.            颜色模式 = 8位色L8,AL44,那么显存的大小就是:
  45.            XSIZE_PHYS * YSIZE_PHYS * 1 * NUM_VSCREENS * NUM_BUFFERS  
  46.      
  47.       这里为了方便起见,将开发板配套的16MB的SDRAM前8MB分配给LCD显存使用,后8MB用于emWin动态内存。
  48.        对于24位色,16位色,8位色,用户可以对其使能三缓冲,并且使能双图层。但是32位色也使能三缓冲和双
  49.        图层的话会超出8MB,所以用户根据自己的情况做显存和emWin动态内存的分配调整。
  50.          举一个例子,对于800*480分辨率的显示屏,使能32位色,三缓冲,那么最终一个图层需要的大小就是
  51.       800 * 480 * 4 * 3  = 4.394MB的空间,如果是双图层,已经超出8MB的分配范围。
  52.      
  53.       (5)为了方便起见,图层2的宏定义LCD_LAYER1_FRAME_BUFFER中的参数4是按照32位色设置的,如果用户的图层1
  54.          使用的是8位色,这里填数字1,如果是16位色,这里填2,如果是24位色,这里填3。
  55. */
  56. #define LCD_LAYER0_FRAME_BUFFER  EXT_SDRAM_ADDR
  57. #define LCD_LAYER1_FRAME_BUFFER  (LCD_LAYER0_FRAME_BUFFER + XSIZE_PHYS * YSIZE_PHYS * 4 * NUM_VSCREENS *
  58. NUM_BUFFERS)
  59. /*
  60.    6. STM32F429/439支持的颜色模式,所有模式都支持,用户可任意配置。
  61.       特别注意如下两个问题:
  62.        (1) 如果用户选择了ARGB8888或者RGB888模式,LCD闪烁比较厉害的话,
  63.            请降低LTDC的时钟大小,在文件bsp_tft_429.c的函数LCD_ConfigLTDC里面设置。
  64.            a. 一般800*480分辨率的显示屏,ARGB8888或者RGB888模式LTDC时钟选择10-20MHz即可。
  65.            b. 480*272分辨率的可以高些,取20MHz左右即可。
  66.        (2) 16位色或者8位色模式,LTDC的时钟频率一般可以比24位色或者32位色的高一倍。
  67. */
  68. #define _CM_ARGB8888      1
  69. #define _CM_RGB888        2
  70. #define _CM_RGB565        3
  71. #define _CM_ARGB1555      4
  72. #define _CM_ARGB4444      5
  73. #define _CM_L8            6
  74. #define _CM_AL44          7
  75. #define _CM_AL88          8
  76. /* 7. 配置图层1的颜色模式和分辨率大小 */
  77. #define COLOR_MODE_0      _CM_RGB565
  78. #define XSIZE_0           XSIZE_PHYS
  79. #define YSIZE_0           YSIZE_PHYS
  80. /* 8. 配置图层2的的颜色模式和分辨率大小 */
  81. #define COLOR_MODE_1      _CM_RGB565
  82. #define XSIZE_1           XSIZE_PHYS
  83. #define YSIZE_1           YSIZE_PHYS
  84. /* 9. 单图层情况下,根据用户选择的颜色模式可自动选择图层1的emWin的驱动和颜色模式 */
  85. #if   (COLOR_MODE_0 == _CM_ARGB8888)
  86.   #define COLOR_CONVERSION_0 GUICC_M8888I
  87.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_32
  88. #elif (COLOR_MODE_0 == _CM_RGB888)
  89.   #define COLOR_CONVERSION_0 GUICC_M888
  90.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_24
  91. #elif (COLOR_MODE_0 == _CM_RGB565)
  92.   #define COLOR_CONVERSION_0 GUICC_M565
  93.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  94. #elif (COLOR_MODE_0 == _CM_ARGB1555)
  95.   #define COLOR_CONVERSION_0 GUICC_M1555I
  96.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  97. #elif (COLOR_MODE_0 == _CM_ARGB4444)
  98.   #define COLOR_CONVERSION_0 GUICC_M4444I
  99.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  100. #elif (COLOR_MODE_0 == _CM_L8)
  101.   #define COLOR_CONVERSION_0 GUICC_8666
  102.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_8
  103. #elif (COLOR_MODE_0 == _CM_AL44)
  104.   #define COLOR_CONVERSION_0 GUICC_1616I
  105.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_8
  106. #elif (COLOR_MODE_0 == _CM_AL88)
  107.   #define COLOR_CONVERSION_0 GUICC_88666I
  108.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  109. #else
  110.   #error Illegal color mode 0!
  111. #endif
  112. /* 10. 双图层情况下,根据用户选择的颜色模式可自动选择图层2的emWin的驱动和颜色模式 */
  113. #if (GUI_NUM_LAYERS > 1)
  114. #if   (COLOR_MODE_1 == _CM_ARGB8888)
  115.   #define COLOR_CONVERSION_1 GUICC_M8888I
  116.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_32
  117. #elif (COLOR_MODE_1 == _CM_RGB888)
  118.   #define COLOR_CONVERSION_1 GUICC_M888
  119.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_24
  120. #elif (COLOR_MODE_1 == _CM_RGB565)
  121.   #define COLOR_CONVERSION_1 GUICC_M565
  122.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  123. #elif (COLOR_MODE_1 == _CM_ARGB1555)
  124.   #define COLOR_CONVERSION_1 GUICC_M1555I
  125.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  126. #elif (COLOR_MODE_1 == _CM_ARGB4444)
  127.   #define COLOR_CONVERSION_1 GUICC_M4444I
  128.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  129. #elif (COLOR_MODE_1 == _CM_L8)
  130.   #define COLOR_CONVERSION_1 GUICC_8666
  131.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_8
  132. #elif (COLOR_MODE_1 == _CM_AL44)
  133.   #define COLOR_CONVERSION_1 GUICC_1616I
  134.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_8
  135. #elif (COLOR_MODE_1 == _CM_AL88)
  136.   #define COLOR_CONVERSION_1 GUICC_88666I
  137.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  138. #else
  139.   #error Illegal color mode 1!
  140. #endif
  141. #else
  142. #undef XSIZE_0
  143. #undef YSIZE_0
  144. #define XSIZE_0       XSIZE_PHYS
  145. #define YSIZE_0       YSIZE_PHYS
  146. #endif
  147. /*11. 配置选项检测,防止配置错误或者某些选项没有配置 */
  148. #ifndef   XSIZE_PHYS
  149.   #error Physical X size of display is not defined!
  150. #endif
  151. #ifndef   YSIZE_PHYS
  152.   #error Physical Y size of display is not defined!
  153. #endif
  154. #ifndef   NUM_VSCREENS
  155.   #define NUM_VSCREENS 1
  156. #else
  157.   #if (NUM_VSCREENS <= 0)
  158.     #error At least one screeen needs to be defined!
  159.   #endif
  160. #endif
  161. #if (NUM_VSCREENS > 1) && (NUM_BUFFERS > 1)
  162.   #error Virtual screens and multiple buffers are not allowed!
  163. #endif
复制代码
    对于这12个配置选项,注释说明已经比较详细。默认情况下,本教程配套的emWin例子都是用的三缓冲,RGB565格式,且仅使用单图层。
程序设计:
任务栈大小分配:
    μCOS-III任务栈大小在os_cfg.h文件中配置:
#define  APP_CFG_TASK_START_STK_SIZE                     512u
#define  APP_CFG_TASK_MsgPro_STK_SIZE                    512u
#define  APP_CFG_TASK_COM_STK_SIZE                       512u
#define  APP_CFG_TASK_USER_IF_STK_SIZE                    512u
#define  APP_CFG_TASK_GUI_STK_SIZE                        1024u
    任务栈大小的单位是4字节,那么每个任务的栈大小如下:
App Task Start   任务:2048字节。
       App Task MspPro任务 :2048字节。
       App Task UserIF  任务:2048字节。
       App Task COM   任务:2048字节。
      App Task GUI    任务:4096字节。
系统栈大小分配:
    μCOS-III的系统栈大小在os_cfg_app.h文件中配置:
        #define  OS_CFG_ISR_STK_SIZE                      512u      
        系统栈大小的单位是4字节,那么这里就是配置系统栈大小为2KB。
μCOS-III初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main(void)
  10. {
  11.     OS_ERR  err;
  12.    
  13.      /* 初始化uC/OS-III 内核 */
  14.     OSInit(&err);
  15.      /* 创建一个启动任务(也就是主任务)。启动任务会创建所有的应用程序任务 */
  16.      OSTaskCreate((OS_TCB       *)&AppTaskStartTCB,  /* 任务控制块地址 */           
  17.                  (CPU_CHAR     *)"App Task Start",  /* 任务名 */
  18.                  (OS_TASK_PTR   )AppTaskStart,      /* 启动任务函数地址 */
  19.                  (void         *)0,                 /* 传递给任务的参数 */
  20.                  (OS_PRIO       )APP_CFG_TASK_START_PRIO, /* 任务优先级 */
  21.                  (CPU_STK      *)&AppTaskStartStk[0],     /* 堆栈基地址 */
  22.                  (CPU_STK_SIZE  )APP_CFG_TASK_START_STK_SIZE / 10, /* 堆栈监测区,这里表示后10%作为监测区 */
  23.                  (CPU_STK_SIZE  )APP_CFG_TASK_START_STK_SIZE,      /* 堆栈空间大小 */
  24.                  (OS_MSG_QTY    )0,  /* 本任务支持接受的最大消息数 */
  25.                  (OS_TICK       )0,  /* 设置时间片 */
  26.                  (void         *)0,  /* 堆栈空间大小 */
  27.                  (OS_OPT        )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
  28.         
  29.                     /*  定义如下:
  30.                        OS_OPT_TASK_STK_CHK      使能检测任务栈,统计任务栈已用的和未用的
  31.                        OS_OPT_TASK_STK_CLR      在创建任务时,清零任务栈
  32.                        OS_OPT_TASK_SAVE_FP      如果CPU有浮点寄存器,则在任务切换时保存浮点寄存器的内容
  33.                     */
  34.                  (OS_ERR       *)&err);
  35.      /* 启动多任务系统,控制权交给uC/OS-III */
  36.     OSStart(&err);                                             
  37.    
  38.     (void)&err;
  39.    
  40.     return (0);
  41. }
复制代码
硬件外设初始化
     硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.      /*
  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
  15.      */
  16.      /* 使能CRC 因为使用STemWin前必须要使能 */
  17.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
  18.    
  19.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
  20.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  21.    
  22.      SystemCoreClockUpdate();    /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */
  23.      bsp_InitUart();        /* 初始化串口 */
  24.      bsp_InitKey();         /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
  25.    
  26.      bsp_InitExtIO();       /* FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */
  27.      bsp_InitLed();         /* 初始LED指示灯端口 */
  28.    
  29.      bsp_InitI2C();         /* 配置I2C总线 */
  30.      bsp_InitSPIBus();       /* 配置SPI总线 */
  31.    
  32.      bsp_InitSFlash();       /* 初始化SPI Flash */
  33.    
  34.      bsp_InitExtSDRAM();   /* 初始化SDRAM */
  35.      bsp_DetectLcdType();  /* 检测触摸板和LCD面板型号, 结果存在全局变量 g_TouchType, g_LcdType */
  36.    
  37.      TOUCH_InitHard();    /* 初始化配置触摸芯片 */
  38.      LCD_ConfigLTDC();     /* 初始化配置LTDC */
  39.    
  40.      result = f_mount(&fs, "0:/", 0);     /* 挂载文件系统 */
  41. }
复制代码
五个μCOS-III任务的实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskStart
  4. *    功能说明: 这是一个启动任务,在多任务系统启动后,必须初始化滴答计数器。本任务主要实现按键和触摸检测。
  5. *    形    参: p_arg 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7.      优 先 级: 2
  8. *********************************************************************************************************
  9. */
  10. static  void  AppTaskStart (void *p_arg)
  11. {
  12.      OS_ERR      err;
  13.      uint8_t  ucCount = 0;
  14.      uint8_t  ucCount1 = 0;
  15.    
  16.     /* 仅用于避免编译器告警,编译器不会产生任何目标代码 */  
  17.     (void)p_arg;
  18.    
  19.      /* BSP 初始化。 BSP = Board Support Package 板级支持包,可以理解为底层驱动。*/
  20.      CPU_Init();  /* 此函数要优先调用,因为外设驱动中使用的us和ms延迟是基于此函数的 */
  21.      bsp_Init();      
  22.      BSP_Tick_Init();
  23.    
  24. #if OS_CFG_STAT_TASK_EN > 0u
  25.      OSStatTaskCPUUsageInit(&err);  
  26. #endif
  27. #ifdef CPU_CFG_INT_DIS_MEAS_EN
  28.     CPU_IntDisMeasMaxCurReset();
  29. #endif
  30.         
  31.      /* 创建应用程序的任务 */
  32.      AppTaskCreate();
  33.    
  34.      /* 创建任务通信 */
  35.      AppObjCreate();
  36.    
  37.     while(1)
  38.     {
  39.          /* 1ms一次触摸扫描,电阻触摸屏 */
  40.          if(g_tTP.Enable == 1)
  41.          {
  42.               TOUCH_Scan();
  43.             
  44.               /* 按键扫描 */
  45.               ucCount++;
  46.               if(ucCount == 10)
  47.               {
  48.                    ucCount = 0;
  49.                    bsp_KeyScan();
  50.               }
  51.              OSTimeDly(1, OS_OPT_TIME_DLY, &err);         
  52.          }
  53.         
  54.          /* 20ms一次触摸扫描,电容触摸屏GT811
  55.             GT811取20ms比较稳定,取10ms偶尔会有跳动。
  56.          */
  57.          if(g_GT811.Enable == 1)
  58.          {
  59.               bsp_KeyScan();
  60.               ucCount1++;
  61.               if(ucCount1 == 2)
  62.               {
  63.                    ucCount1 = 0;
  64.                    GT811_OnePiontScan();
  65.               }
  66.              OSTimeDly(10, OS_OPT_TIME_DLY, &err);     
  67.          }
  68.         
  69.          /* 10ms一次触摸扫描,电容触摸屏FT5X06 */
  70.          if(g_tFT5X06.Enable == 1)
  71.          {
  72.               bsp_KeyScan();
  73.               FT5X06_OnePiontScan();
  74.              OSTimeDly(10, OS_OPT_TIME_DLY, &err);
  75.          }
  76.     }   
  77. }
  78. /*
  79. *********************************************************************************************************
  80. *    函 数 名: AppTaskMsgPro
  81. *    功能说明: 实现截图功能,将图片以BMP格式保存到SD卡中
  82. *    形    参: p_arg 是在创建该任务时传递的形参
  83. *    返 回 值: 无
  84.      优 先 级: 3
  85. *********************************************************************************************************
  86. */
  87. static void AppTaskMsgPro(void *p_arg)
  88. {
  89.      uint32_t ulStart, ulEnd;
  90.      OS_ERR      err;
  91.      uint8_t       Pic_Name = 0;
  92.      char buf[20];
  93.      (void)p_arg;
  94.          
  95.      while(1)
  96.      {   
  97.           /* 等待获取信号量同步消息,接收到后执行串口打印 */
  98.          OSSemPend((OS_SEM *)&SEM_SYNCH,
  99.                      (OS_TICK )0,
  100.                      (OS_OPT  )OS_OPT_PEND_BLOCKING,
  101.                      (CPU_TS  )0,
  102.                      (OS_ERR *)&err);
  103.         
  104.          if(err == OS_ERR_NONE)
  105.          {   
  106.               sprintf(buf,"0:/PicSave/%d.bmp",Pic_Name);
  107.             
  108.               /* 记录截图前起始时间 */
  109.               ulStart = OSTimeGet(&err);
  110.             
  111.               /* 开启调度锁 */
  112.               OSSchedLock(&err);
  113.             
  114.               /* 如果SD卡中没有PicSave文件,会进行创建 */
  115.               result = f_mkdir("0:/PicSave");
  116.             
  117.               /* 创建截图 */
  118.               result = f_open(&file,buf, FA_WRITE|FA_CREATE_ALWAYS);
  119.             
  120.               /* 向SD卡绘制BMP图片 */
  121.               GUI_BMP_Serialize(_WriteByte2File, &file);
  122.             
  123.               /* 创建完成后关闭file */
  124.              result = f_close(&file);
  125.             
  126.               /* 开启调度锁 */
  127.               OSSchedUnlock(&err);
  128.             
  129.               /* 记录截图后时间并获取截图过程耗时 */
  130.               ulEnd = OSTimeGet(&err);
  131.               ulEnd -= ulStart;
  132.             
  133.               App_Printf("截图完成,耗时 = %dms\\r\\n", ulEnd);
  134.               Pic_Name++;      
  135.          }                                                                                                                  
  136.      }  
  137. }
  138. /*
  139. *********************************************************************************************************
  140. *    函 数 名: AppTaskUserIF
  141. *    功能说明: 按键消息处理
  142. *    形    参: p_arg 是在创建该任务时传递的形参
  143. *    返 回 值: 无
  144.      优 先 级: 4
  145. *********************************************************************************************************
  146. */
  147. static void AppTaskUserIF(void *p_arg)
  148. {
  149.      OS_ERR      err;
  150.      uint8_t  ucKeyCode;
  151.    
  152.      (void)p_arg;                /* 避免编译器报警 */
  153.    
  154.      while (1)
  155.      {      
  156.          ucKeyCode = bsp_GetKey();
  157.         
  158.          if (ucKeyCode != KEY_NONE)
  159.          {
  160.               switch (ucKeyCode)
  161.               {
  162.                    case KEY_DOWN_K1:             /* K1键按下 打印任务执行情况 */
  163.                        DispTaskInfo();        
  164.                        break;
  165.                   
  166.                    case KEY_DOWN_K2:             /* K2键按下 向消息队列发送数据 */
  167.                        OSSemPost((OS_SEM *)&SEM_SYNCH,
  168.                                   (OS_OPT  )OS_OPT_POST_1,
  169.                                   (OS_ERR *)&err);
  170.                        break;
  171.                   
  172.                    default:                     /* 其他的键值不处理 */
  173.                        break;
  174.               }
  175.          }
  176.         
  177.          OSTimeDly(20, OS_OPT_TIME_DLY, &err);
  178.      }
  179. }
  180. /*
  181. *********************************************************************************************************
  182. *    函 数 名: AppTaskCom
  183. *    功能说明: 暂未使用
  184. *    形    参: p_arg 是在创建该任务时传递的形参
  185. *    返 回 值: 无
  186.      优 先 级: 5
  187. *********************************************************************************************************
  188. */
  189. static void AppTaskCOM(void *p_arg)
  190. {
  191.      OS_ERR  err;      
  192.    
  193.      (void)p_arg;
  194.    
  195.      while(1)
  196.      {   
  197.          OSTimeDly(500, OS_OPT_TIME_DLY, &err);
  198.      }                                                                                                
  199. }
  200. /*
  201. *********************************************************************************************************
  202. *    函 数 名: AppTaskGUI
  203. *    功能说明: GUI任务,最低优先级                        
  204. *    形    参:p_arg 是在创建该任务时传递的形参
  205. *    返 回 值: 无
  206. *   优 先 级:OS_CFG_PRIO_MAX - 4u
  207. *********************************************************************************************************
  208. */
  209. static void AppTaskGUI(void *p_arg)
  210. {
  211.     (void)p_arg;       /* 避免编译器告警 */
  212.         
  213.      while (1)
  214.      {
  215.          MainTask();
  216.      }
  217. }
复制代码
emWin任务的具体实现(在MainTask.c文件里面):
  1. #include "MainTask.h"
  2. #include "includes.h"
  3. /*
  4. *********************************************************************************************************
  5. *                                             变量
  6. *********************************************************************************************************
  7. */
  8. uint8_t tempbuf[4096];  /* 从SD卡读取数据的缓冲 */
  9. /*
  10. *********************************************************************************************************
  11. *                                               对话框信息
  12. *********************************************************************************************************
  13. */
  14. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  15.     { FRAMEWIN_CreateIndirect,  "安富莱电子",     0,          0,  0,  480, 272,FRAMEWIN_CF_MOVEABLE, 0},
  16.      { BUTTON_CreateIndirect,    "安富莱电子",     GUI_ID_BUTTON0,  10, 150, 400, 50, 0, 0},
  17.     { TEXT_CreateIndirect,      "安富莱电子AaAa-12点阵半角全角",   GUI_ID_TEXT0,   0, 10, 480, 33, 0,0},
  18.     { TEXT_CreateIndirect,      "安富莱电子AaAa-16点阵半角全角",   GUI_ID_TEXT1,   0, 40, 480, 33, 0,0},
  19.     { TEXT_CreateIndirect,      "安富莱电子AaAa-24点阵半角全角",   GUI_ID_TEXT2,   0, 70, 480, 72, 0,0},
  20.      { TEXT_CreateIndirect,      "安富莱电子AaAa-32点阵半全角",     GUI_ID_TEXT3,   0, 100, 480, 72, 0,0},
  21. };
  22. /*
  23. *********************************************************************************************************
  24. *    函 数 名: PaintDialog
  25. *    功能说明: 重绘
  26. *    形    参:pMsg  消息指针
  27. *    返 回 值: 无
  28. *********************************************************************************************************
  29. */
  30. void PaintDialog(WM_MESSAGE * pMsg)
  31. {
  32. //    WM_HWIN hWin = pMsg->hWin;
  33.    
  34. }
  35. /*
  36. *********************************************************************************************************
  37. *    函 数 名: InitDialog
  38. *    功能说明: 对话框初始化
  39. *    形    参:pMsg  消息指针
  40. *    返 回 值: 无
  41. *********************************************************************************************************
  42. */
  43. void InitDialog(WM_MESSAGE * pMsg)
  44. {
  45.     WM_HWIN hWin = pMsg->hWin;
  46.     //
  47.     //FRAMEWIN
  48.     //
  49.     FRAMEWIN_SetFont(hWin,&GUI_FontHZ24);
  50.     FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
  51.     FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);
  52.     FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);
  53.     FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);
  54.     FRAMEWIN_SetTitleHeight(hWin,35);
  55.    
  56.     //
  57.     //GUI_ID_BUTTON0
  58.     //
  59.     BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&GUI_FontHZ32);
  60.    
  61.     //
  62.     //GUI_ID_TEXT0
  63.     //
  64.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED);
  65.     TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontHZ12);
  66.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_YELLOW);
  67.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&GUI_FontHZ16);
  68.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
  69.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&GUI_FontHZ24);
  70.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT3), GUI_ORANGE);
  71.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&GUI_FontHZ32);
  72. }
  73. /*
  74. *********************************************************************************************************
  75. *    函 数 名: _cbCallback
  76. *    功能说明: 对话框回调函数
  77. *    形    参: pMsg  消息指针
  78. *    返 回 值: 无
  79. *********************************************************************************************************
  80. */
  81. static void _cbCallback(WM_MESSAGE * pMsg)
  82. {
  83.     int NCode, Id;
  84.     WM_HWIN hWin = pMsg->hWin;
  85.     switch (pMsg->MsgId)
  86.     {
  87.         case WM_PAINT:
  88.             PaintDialog(pMsg);
  89.             break;
  90.         
  91.         case WM_INIT_DIALOG:
  92.             InitDialog(pMsg);
  93.             break;
  94.         
  95.         case WM_KEY:
  96.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  97.             {
  98.                 case GUI_KEY_ESCAPE:
  99.                     GUI_EndDialog(hWin, 1);
  100.                     break;
  101.                   
  102.                 case GUI_KEY_ENTER:
  103.                     GUI_EndDialog(hWin, 0);
  104.                     break;
  105.             }
  106.             break;
  107.             
  108.         case WM_NOTIFY_PARENT:
  109.             Id = WM_GetId(pMsg->hWinSrc);
  110.             NCode = pMsg->Data.v;      
  111.             switch (Id)
  112.             {
  113.                 case GUI_ID_OK:
  114.                     if(NCode==WM_NOTIFICATION_RELEASED)
  115.                         GUI_EndDialog(hWin, 0);
  116.                     break;
  117.                      
  118.                 case GUI_ID_CANCEL:
  119.                     if(NCode==WM_NOTIFICATION_RELEASED)
  120.                         GUI_EndDialog(hWin, 0);
  121.                     break;
  122.             }
  123.             break;
  124.             
  125.         default:
  126.             WM_DefaultProc(pMsg);
  127.     }
  128. }
  129. /*
  130. *********************************************************************************************************
  131. *    函 数 名: LoadFontLib()
  132. *    功能说明: 从SD卡中加载字库文件到SPI FLASH
  133. *    形    参: 无      
  134. *    返 回 值: 无
  135. *********************************************************************************************************
  136. */
  137. void LoadFontLib(void)
  138. {
  139.      float FinishPecent;
  140.     uint32_t Count = 0;
  141.      uint16_t y, i;
  142.      uint8_t ucState;
  143.      char cDispBuf[80];
  144.    
  145.      /* 清屏 */
  146.      GUI_SetBkColor(GUI_BLUE);
  147.      GUI_Clear();
  148.    
  149.      /* 设置字体 */
  150.      GUI_SetFont(GUI_FONT_20_1);
  151.     y = 0;
  152.      /* 第1步:显示操作说明 ***************************************************************/
  153.      GUI_DispStringAt("SPI Flash Chinese character Lab", 0, y);
  154.      y += 20;
  155.    
  156.      GUI_DispStringAt("1. Please make sure the font.bin is saved in SD", 0, y);
  157.      y += 20;
  158.    
  159.      GUI_DispStringAt("2. if the font.bin is not saved in SD, this lab will fail", 0, y);
  160.      y += 20;
  161.    
  162.      /* 等待10s后开始进行复制,方便客户看屏幕上的显示信息 */
  163.      for(i = 0; i < 11; i++)
  164.      {
  165.          sprintf(cDispBuf, "3. 10 seconds will start, %ds..  ", 10 - i);
  166.          GUI_DispStringAt(cDispBuf, 0, y);
  167.          GUI_Delay(1000);
  168.      }
  169.      y += 20;
  170.    
  171.    
  172.      /* 第2步:打开文件 ***************************************************************/
  173.      result = f_open(&file, "font.bin", FA_OPEN_EXISTING | FA_READ);
  174.      if (result !=  FR_OK)
  175.      {
  176.          GUI_DispStringAt("font.bin open failed", 0, y);
  177.          y += 20;
  178.      }
  179.      /* 第3步:复制SD卡中字库文件font.bin到SPI FLASH **********************************/
  180.      for(;;)
  181.      {
  182.          /* 读取一个扇区的数据到buf */
  183.          result = f_read(&file, &tempbuf, g_tSF.PageSize, &bw);
  184.         
  185.          /* 读取出错或者读取完毕,退出 */
  186.          if ((result != FR_OK)||bw == 0)
  187.          {
  188.               break;
  189.          }
  190.         
  191.          /* 写数据到SPI FLASH */
  192.          ucState = sf_WriteBuffer(tempbuf, Count*g_tSF.PageSize, g_tSF.PageSize);
  193.         
  194.          /* 如果返回0,表示复制失败 */
  195.          if(ucState == 0)
  196.          {
  197.               GUI_DispStringAt("copy failed                  ", 0, y);
  198.               break;
  199.          }
  200.         
  201.           /* 显示复制进度 */
  202.          Count = Count + 1;
  203.          FinishPecent = (float)(Count* g_tSF.PageSize) / file.fsize;
  204.          sprintf(cDispBuf, "copying:%02d%%", (uint8_t)(FinishPecent*100));
  205.          GUI_DispStringAt(cDispBuf, 0, y);
  206.      }
  207.    
  208.      /* 等待1秒后开始进去emWin主界面 */
  209.      GUI_Delay(1000);
  210. }
  211. /*
  212. *********************************************************************************************************
  213. *    函 数 名: MainTask
  214. *    功能说明: GUI主函数
  215. *    形    参: 无
  216. *    返 回 值: 无
  217. *********************************************************************************************************
  218. */
  219. void MainTask(void)
  220. {
  221.      /* 初始化 */
  222.      GUI_Init();
  223.       
  224.      /*
  225.       关于多缓冲和窗口内存设备的设置说明
  226.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  227.            WM_MULTIBUF_Enable(1);
  228.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  229.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  230.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  231.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  232.         4. 所有emWin例子默认是开启三缓冲。
  233.      */
  234.      WM_MULTIBUF_Enable(1);
  235.      /*
  236.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  237.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  238.      */
  239.     //TOUCH_Calibration();
  240.    
  241.      /* 初始化使用GUI以前,先将字库从SD卡中加载到SP FLASH里面 */
  242.      LoadFontLib();
  243.    
  244.      /* 调用此函数会自动的刷新桌面窗口 */
  245.      WM_SetDesktopColor(GUI_BLUE);
  246.      /* 创建对话框 */
  247.      GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
  248.    
  249.      while(1)
  250.      {
  251.          GUI_Delay(10);
  252.      }
  253. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-22 15:56:28 | 显示全部楼层
25.7 实验例程说明(裸机)


配套例子:
     V6-533_STemWin实验_全字库实现,GB2312编码(裸机)
实验目的:
    1.     学习emWin的GB2312编码全字库的使用方法。
    2.     emWin功能的实现在MainTask.c文件里面。
支持点阵:
    1.     支持12点阵,16点阵,24点阵以及32点阵汉字。
    2.     6X12点阵的ASCII,8X16点阵的ASCII,12X24点阵的ASCII,16X32点阵的ASCII
字库存储方式:
    1.     字库存储到SPI FLASH里面。
实验步骤:
    1.     将字库文件font.bin放到SD卡根目录中,系统上电后会将其加载到SPI FLASH里面。
    2.     板子上电后会有一个加载进度指示,存储到SPI FLASH成功后会显示一个对话框。
实验注意:
    1.     实验所需的字库文件font.bin已经存储到本工程的Doc文件夹下,使用此例子前,请务必将这个文件存储到SD卡根目录中,并将SD卡插到开发板上面。
STemWin界面显示效果:
    800*480分辨率界面效果。
25.9.png


STemWin动态内存配置:
    GUIConf.c文件中的配置如下:
  1. #define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
  2. #if EX_SRAM
  3. #define GUI_NUMBYTES  (1024*1024*8)
  4. #else
  5. #define GUI_NUMBYTES  (100*1024)
  6. #endif
复制代码

    通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:
#define EX_SRAM    1 表示使用外部SDRAM作为emWin动态内存,大小8MB。
#define EX_SRAM    0 表示使用内部SRAM作为emWin动态内存,大小100KB。
默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。
STemWin底层接口配置:
    LCDConf_Lin_Template.c文件中共12项emWin配置:
  1. /*
  2. **********************************************************************************************************
  3.                                           用户可以配置的选项
  4. **********************************************************************************************************
  5. */
  6. /* 0. 在官方代码的基础上再做优化,官方的部分函数效率低,耗内存, 0表示优化 */
  7. #define emWin_Optimize   0
  8. /*
  9.   1. 显示屏的物理分辨率,驱动已经做了显示屏自适应,支持4.3寸,5寸和7寸屏
  10.      这里填写自适应显示屏中的最大分辨率。
  11. */
  12. #define XSIZE_PHYS       800
  13. #define YSIZE_PHYS       480
  14. /* 2. 多缓冲 / 虚拟屏,多缓冲和虚拟屏不可同时使用,emWin不支持 */
  15. #define NUM_BUFFERS      3 /* 定义多缓冲个数,仅可以设置1,2和3,也就是最大支持三缓冲 */
  16. #define NUM_VSCREENS     1 /* 定义虚拟屏个数 */
  17. /* 3. 没有图层激活时,背景色设置, 暂时未用到 */
  18. #define BK_COLOR         GUI_DARKBLUE
  19. /*
  20.    4. 重定义图层数,对于STM32F429/439,用户可以选择一个图层或者两个图层,不支持三图层
  21.       (1). 设置GUI_NUM_LAYERS = 1时,即仅使用图层1时,默认触摸值是发送给图层1的。
  22.        (2). 设置GUI_NUM_LAYERS = 2时,即图层1和图层2都已经使能,此时图层2是顶层,
  23.             用户需要根据自己的使用情况设置如下两个地方。
  24.             a. 在bsp_touch.c文件中的函数TOUCH_InitHard里面设置参数State.Layer = 1,1就表示
  25.                给图层2发送触摸值。
  26.             b. 调用GUI_Init函数后,调用函数GUI_SelectLayer(1), 设置当前操作的是图层2。
  27. */
  28. #undef  GUI_NUM_LAYERS
  29. #define GUI_NUM_LAYERS    1
  30. /*
  31.    5. 设置图层1和图层2对应的显存地址
  32.       (1) EXT_SDRAM_ADDR 是SDRAM的首地址。
  33.       (2) LCD_LAYER0_FRAME_BUFFER 是图层1的显存地址。
  34.        (3) LCD_LAYER1_FRAME_BUFFER 是图层2的显存地址。
  35.        (4) 每个图层的显存大小比较考究,这里进行下简单的说明。
  36.            如果用户选择的颜色模式 = 32位色ARGB8888,显存的大小:
  37.            XSIZE_PHYS * YSIZE_PHYS * 4 * NUM_VSCREENS * NUM_BUFFERS
  38.          
  39.            颜色模式 = 24位色RGB888,显存的大小:
  40.            XSIZE_PHYS * YSIZE_PHYS * 3 * NUM_VSCREENS * NUM_BUFFERS
  41.          
  42.            颜色模式 = 16位色RGB566,ARGB1555, ARGB4444,AL88,那么显存的大小就是:
  43.            XSIZE_PHYS * YSIZE_PHYS * 2 * NUM_VSCREENS * NUM_BUFFERS
  44.            颜色模式 = 8位色L8,AL44,那么显存的大小就是:
  45.            XSIZE_PHYS * YSIZE_PHYS * 1 * NUM_VSCREENS * NUM_BUFFERS  
  46.      
  47.       这里为了方便起见,将开发板配套的16MB的SDRAM前8MB分配给LCD显存使用,后8MB用于emWin动态内存。
  48.        对于24位色,16位色,8位色,用户可以对其使能三缓冲,并且使能双图层。但是32位色也使能三缓冲和双
  49.        图层的话会超出8MB,所以用户根据自己的情况做显存和emWin动态内存的分配调整。
  50.          举一个例子,对于800*480分辨率的显示屏,使能32位色,三缓冲,那么最终一个图层需要的大小就是
  51.       800 * 480 * 4 * 3  = 4.394MB的空间,如果是双图层,已经超出8MB的分配范围。
  52.      
  53.       (5)为了方便起见,图层2的宏定义LCD_LAYER1_FRAME_BUFFER中的参数4是按照32位色设置的,如果用户的图层1
  54.          使用的是8位色,这里填数字1,如果是16位色,这里填2,如果是24位色,这里填3。
  55. */
  56. #define LCD_LAYER0_FRAME_BUFFER  EXT_SDRAM_ADDR
  57. #define LCD_LAYER1_FRAME_BUFFER  (LCD_LAYER0_FRAME_BUFFER + XSIZE_PHYS * YSIZE_PHYS * 4 * NUM_VSCREENS *
  58. NUM_BUFFERS)
  59. /*
  60.    6. STM32F429/439支持的颜色模式,所有模式都支持,用户可任意配置。
  61.       特别注意如下两个问题:
  62.        (1) 如果用户选择了ARGB8888或者RGB888模式,LCD闪烁比较厉害的话,
  63.            请降低LTDC的时钟大小,在文件bsp_tft_429.c的函数LCD_ConfigLTDC里面设置。
  64.            a. 一般800*480分辨率的显示屏,ARGB8888或者RGB888模式LTDC时钟选择10-20MHz即可。
  65.            b. 480*272分辨率的可以高些,取20MHz左右即可。
  66.        (2) 16位色或者8位色模式,LTDC的时钟频率一般可以比24位色或者32位色的高一倍。
  67. */
  68. #define _CM_ARGB8888      1
  69. #define _CM_RGB888        2
  70. #define _CM_RGB565        3
  71. #define _CM_ARGB1555      4
  72. #define _CM_ARGB4444      5
  73. #define _CM_L8            6
  74. #define _CM_AL44          7
  75. #define _CM_AL88          8
  76. /* 7. 配置图层1的颜色模式和分辨率大小 */
  77. #define COLOR_MODE_0      _CM_RGB565
  78. #define XSIZE_0           XSIZE_PHYS
  79. #define YSIZE_0           YSIZE_PHYS
  80. /* 8. 配置图层2的的颜色模式和分辨率大小 */
  81. #define COLOR_MODE_1      _CM_RGB565
  82. #define XSIZE_1           XSIZE_PHYS
  83. #define YSIZE_1           YSIZE_PHYS
  84. /* 9. 单图层情况下,根据用户选择的颜色模式可自动选择图层1的emWin的驱动和颜色模式 */
  85. #if   (COLOR_MODE_0 == _CM_ARGB8888)
  86.   #define COLOR_CONVERSION_0 GUICC_M8888I
  87.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_32
  88. #elif (COLOR_MODE_0 == _CM_RGB888)
  89.   #define COLOR_CONVERSION_0 GUICC_M888
  90.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_24
  91. #elif (COLOR_MODE_0 == _CM_RGB565)
  92.   #define COLOR_CONVERSION_0 GUICC_M565
  93.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  94. #elif (COLOR_MODE_0 == _CM_ARGB1555)
  95.   #define COLOR_CONVERSION_0 GUICC_M1555I
  96.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  97. #elif (COLOR_MODE_0 == _CM_ARGB4444)
  98.   #define COLOR_CONVERSION_0 GUICC_M4444I
  99.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  100. #elif (COLOR_MODE_0 == _CM_L8)
  101.   #define COLOR_CONVERSION_0 GUICC_8666
  102.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_8
  103. #elif (COLOR_MODE_0 == _CM_AL44)
  104.   #define COLOR_CONVERSION_0 GUICC_1616I
  105.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_8
  106. #elif (COLOR_MODE_0 == _CM_AL88)
  107.   #define COLOR_CONVERSION_0 GUICC_88666I
  108.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  109. #else
  110.   #error Illegal color mode 0!
  111. #endif
  112. /* 10. 双图层情况下,根据用户选择的颜色模式可自动选择图层2的emWin的驱动和颜色模式 */
  113. #if (GUI_NUM_LAYERS > 1)
  114. #if   (COLOR_MODE_1 == _CM_ARGB8888)
  115.   #define COLOR_CONVERSION_1 GUICC_M8888I
  116.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_32
  117. #elif (COLOR_MODE_1 == _CM_RGB888)
  118.   #define COLOR_CONVERSION_1 GUICC_M888
  119.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_24
  120. #elif (COLOR_MODE_1 == _CM_RGB565)
  121.   #define COLOR_CONVERSION_1 GUICC_M565
  122.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  123. #elif (COLOR_MODE_1 == _CM_ARGB1555)
  124.   #define COLOR_CONVERSION_1 GUICC_M1555I
  125.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  126. #elif (COLOR_MODE_1 == _CM_ARGB4444)
  127.   #define COLOR_CONVERSION_1 GUICC_M4444I
  128.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  129. #elif (COLOR_MODE_1 == _CM_L8)
  130.   #define COLOR_CONVERSION_1 GUICC_8666
  131.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_8
  132. #elif (COLOR_MODE_1 == _CM_AL44)
  133.   #define COLOR_CONVERSION_1 GUICC_1616I
  134.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_8
  135. #elif (COLOR_MODE_1 == _CM_AL88)
  136.   #define COLOR_CONVERSION_1 GUICC_88666I
  137.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  138. #else
  139.   #error Illegal color mode 1!
  140. #endif
  141. #else
  142. #undef XSIZE_0
  143. #undef YSIZE_0
  144. #define XSIZE_0       XSIZE_PHYS
  145. #define YSIZE_0       YSIZE_PHYS
  146. #endif
  147. /*11. 配置选项检测,防止配置错误或者某些选项没有配置 */
  148. #ifndef   XSIZE_PHYS
  149.   #error Physical X size of display is not defined!
  150. #endif
  151. #ifndef   YSIZE_PHYS
  152.   #error Physical Y size of display is not defined!
  153. #endif
  154. #ifndef   NUM_VSCREENS
  155.   #define NUM_VSCREENS 1
  156. #else
  157.   #if (NUM_VSCREENS <= 0)
  158.     #error At least one screeen needs to be defined!
  159.   #endif
  160. #endif
  161. #if (NUM_VSCREENS > 1) && (NUM_BUFFERS > 1)
  162.   #error Virtual screens and multiple buffers are not allowed!
  163. #endif
复制代码

    对于这12个配置选项,注释说明已经比较详细。默认情况下,本教程配套的emWin例子都是用的三缓冲,RGB565格式,且仅使用单图层。
程序设计:
栈大小分配:
    系统栈大小在startup_stm32f429_439xx.s文件中配置:
25.10.png

    栈大小的单位是字节,那么这里配置的系统栈大小就是8192字节。
主函数初始化:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: main
  4. *    功能说明: 标准c程序入口。
  5. *    形    参: 无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. int main (void)
  10. {   
  11.      /* 初始化外设 */
  12.      bsp_Init();
  13.      /* 进入emWin主函数 */
  14.      MainTask();
  15. }
复制代码

硬件外设初始化
    硬件外设的初始化是在bsp.c文件实现:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: bsp_Init
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
  5. *    形    参:无
  6. *    返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void bsp_Init(void)
  10. {
  11.      /*
  12.          由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
  13.          启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
  14.          系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
  15.      */
  16.      /* 使能CRC 因为使用STemWin前必须要使能 */
  17.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
  18.    
  19.      /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
  20.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  21.    
  22.      SystemCoreClockUpdate();    /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */
  23.      bsp_InitUart();        /* 初始化串口 */
  24.      bsp_InitKey();         /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
  25.    
  26.      bsp_InitExtIO();       /* FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */
  27.      bsp_InitLed();         /* 初始LED指示灯端口 */
  28.    
  29.      bsp_InitI2C();         /* 配置I2C总线 */
  30.      bsp_InitSPIBus();       /* 配置SPI总线 */
  31.    
  32.      bsp_InitSFlash();       /* 初始化SPI Flash */
  33.    
  34.      bsp_InitExtSDRAM();   /* 初始化SDRAM */
  35.      bsp_DetectLcdType();  /* 检测触摸板和LCD面板型号, 结果存在全局变量 g_TouchType, g_LcdType */
  36.    
  37.      TOUCH_InitHard();    /* 初始化配置触摸芯片 */
  38.      LCD_ConfigLTDC();     /* 初始化配置LTDC */
  39.    
  40.      result = f_mount(&fs, "0:/", 0);     /* 挂载文件系统 */
  41. }
复制代码

emWin功能的具体实现(在MainTask.c文件里面):
  1. #include "MainTask.h"
  2. #include "bsp.h"
  3. /*
  4. *********************************************************************************************************
  5. *                                             变量
  6. *********************************************************************************************************
  7. */
  8. uint8_t tempbuf[4096];  /* 从SD卡读取数据的缓冲 */
  9. /*
  10. *********************************************************************************************************
  11. *                                               对话框信息
  12. *********************************************************************************************************
  13. */
  14. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  15.     { FRAMEWIN_CreateIndirect,  "安富莱电子",     0,          0,  0,  480, 272,FRAMEWIN_CF_MOVEABLE, 0},
  16.      { BUTTON_CreateIndirect,    "安富莱电子",     GUI_ID_BUTTON0,  10, 150, 400, 50, 0, 0},
  17.     { TEXT_CreateIndirect,      "安富莱电子AaAa-12点阵半角全角",   GUI_ID_TEXT0,   0, 10, 480, 33, 0,0},
  18.     { TEXT_CreateIndirect,      "安富莱电子AaAa-16点阵半角全角",   GUI_ID_TEXT1,   0, 40, 480, 33, 0,0},
  19.     { TEXT_CreateIndirect,      "安富莱电子AaAa-24点阵半角全角",   GUI_ID_TEXT2,   0, 70, 480, 72, 0,0},
  20.      { TEXT_CreateIndirect,      "安富莱电子AaAa-32点阵半全角",     GUI_ID_TEXT3,   0, 100, 480, 72, 0,0},
  21. };
  22. /*
  23. *********************************************************************************************************
  24. *    函 数 名: PaintDialog
  25. *    功能说明: 重绘
  26. *    形    参:pMsg  消息指针
  27. *    返 回 值: 无
  28. *********************************************************************************************************
  29. */
  30. void PaintDialog(WM_MESSAGE * pMsg)
  31. {
  32. //    WM_HWIN hWin = pMsg->hWin;
  33.    
  34. }
  35. /*
  36. *********************************************************************************************************
  37. *    函 数 名: InitDialog
  38. *    功能说明: 对话框初始化
  39. *    形    参:pMsg  消息指针
  40. *    返 回 值: 无
  41. *********************************************************************************************************
  42. */
  43. void InitDialog(WM_MESSAGE * pMsg)
  44. {
  45.     WM_HWIN hWin = pMsg->hWin;
  46.     //
  47.     //FRAMEWIN
  48.     //
  49.     FRAMEWIN_SetFont(hWin,&GUI_FontHZ24);
  50.     FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
  51.     FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);
  52.     FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);
  53.     FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);
  54.     FRAMEWIN_SetTitleHeight(hWin,35);
  55.    
  56.     //
  57.     //GUI_ID_BUTTON0
  58.     //
  59.     BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&GUI_FontHZ32);
  60.    
  61.     //
  62.     //GUI_ID_TEXT0
  63.     //
  64.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT0), GUI_RED);
  65.     TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontHZ12);
  66.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_YELLOW);
  67.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&GUI_FontHZ16);
  68.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
  69.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&GUI_FontHZ24);
  70.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT3), GUI_ORANGE);
  71.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&GUI_FontHZ32);
  72. }
  73. /*
  74. *********************************************************************************************************
  75. *    函 数 名: _cbCallback
  76. *    功能说明: 对话框回调函数
  77. *    形    参: pMsg  消息指针
  78. *    返 回 值: 无
  79. *********************************************************************************************************
  80. */
  81. static void _cbCallback(WM_MESSAGE * pMsg)
  82. {
  83.     int NCode, Id;
  84.     WM_HWIN hWin = pMsg->hWin;
  85.     switch (pMsg->MsgId)
  86.     {
  87.         case WM_PAINT:
  88.             PaintDialog(pMsg);
  89.             break;
  90.         
  91.         case WM_INIT_DIALOG:
  92.             InitDialog(pMsg);
  93.             break;
  94.         
  95.         case WM_KEY:
  96.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  97.             {
  98.                 case GUI_KEY_ESCAPE:
  99.                     GUI_EndDialog(hWin, 1);
  100.                     break;
  101.                   
  102.                 case GUI_KEY_ENTER:
  103.                     GUI_EndDialog(hWin, 0);
  104.                     break;
  105.             }
  106.             break;
  107.             
  108.         case WM_NOTIFY_PARENT:
  109.             Id = WM_GetId(pMsg->hWinSrc);
  110.             NCode = pMsg->Data.v;      
  111.             switch (Id)
  112.             {
  113.                 case GUI_ID_OK:
  114.                     if(NCode==WM_NOTIFICATION_RELEASED)
  115.                         GUI_EndDialog(hWin, 0);
  116.                     break;
  117.                      
  118.                 case GUI_ID_CANCEL:
  119.                     if(NCode==WM_NOTIFICATION_RELEASED)
  120.                         GUI_EndDialog(hWin, 0);
  121.                     break;
  122.             }
  123.             break;
  124.             
  125.         default:
  126.             WM_DefaultProc(pMsg);
  127.     }
  128. }
  129. /*
  130. *********************************************************************************************************
  131. *    函 数 名: LoadFontLib()
  132. *    功能说明: 从SD卡中加载字库文件到SPI FLASH
  133. *    形    参: 无      
  134. *    返 回 值: 无
  135. *********************************************************************************************************
  136. */
  137. void LoadFontLib(void)
  138. {
  139.      float FinishPecent;
  140.     uint32_t Count = 0;
  141.      uint16_t y, i;
  142.      uint8_t ucState;
  143.      char cDispBuf[80];
  144.    
  145.      /* 清屏 */
  146.      GUI_SetBkColor(GUI_BLUE);
  147.      GUI_Clear();
  148.    
  149.      /* 设置字体 */
  150.      GUI_SetFont(GUI_FONT_20_1);
  151.     y = 0;
  152.      /* 第1步:显示操作说明 ***************************************************************/
  153.      GUI_DispStringAt("SPI Flash Chinese character Lab", 0, y);
  154.      y += 20;
  155.    
  156.      GUI_DispStringAt("1. Please make sure the font.bin is saved in SD", 0, y);
  157.      y += 20;
  158.    
  159.      GUI_DispStringAt("2. if the font.bin is not saved in SD, this lab will fail", 0, y);
  160.      y += 20;
  161.    
  162.      /* 等待10s后开始进行复制,方便客户看屏幕上的显示信息 */
  163.      for(i = 0; i < 11; i++)
  164.      {
  165.          sprintf(cDispBuf, "3. 10 seconds will start, %ds..  ", 10 - i);
  166.          GUI_DispStringAt(cDispBuf, 0, y);
  167.          GUI_Delay(1000);
  168.      }
  169.      y += 20;
  170.    
  171.    
  172.      /* 第2步:打开文件 ***************************************************************/
  173.      result = f_open(&file, "font.bin", FA_OPEN_EXISTING | FA_READ);
  174.      if (result !=  FR_OK)
  175.      {
  176.          GUI_DispStringAt("font.bin open failed", 0, y);
  177.          y += 20;
  178.      }
  179.      /* 第3步:复制SD卡中字库文件font.bin到SPI FLASH **********************************/
  180.      for(;;)
  181.      {
  182.          /* 读取一个扇区的数据到buf */
  183.          result = f_read(&file, &tempbuf, g_tSF.PageSize, &bw);
  184.         
  185.          /* 读取出错或者读取完毕,退出 */
  186.          if ((result != FR_OK)||bw == 0)
  187.          {
  188.               break;
  189.          }
  190.         
  191.          /* 写数据到SPI FLASH */
  192.          ucState = sf_WriteBuffer(tempbuf, Count*g_tSF.PageSize, g_tSF.PageSize);
  193.         
  194.          /* 如果返回0,表示复制失败 */
  195.          if(ucState == 0)
  196.          {
  197.               GUI_DispStringAt("copy failed                  ", 0, y);
  198.               break;
  199.          }
  200.         
  201.           /* 显示复制进度 */
  202.          Count = Count + 1;
  203.          FinishPecent = (float)(Count* g_tSF.PageSize) / file.fsize;
  204.          sprintf(cDispBuf, "copying:%02d%%", (uint8_t)(FinishPecent*100));
  205.          GUI_DispStringAt(cDispBuf, 0, y);
  206.      }
  207.    
  208.      /* 等待1秒后开始进去emWin主界面 */
  209.      GUI_Delay(1000);
  210. }
  211. /*
  212. *********************************************************************************************************
  213. *    函 数 名: MainTask
  214. *    功能说明: GUI主函数
  215. *    形    参: 无
  216. *    返 回 值: 无
  217. *********************************************************************************************************
  218. */
  219. void MainTask(void)
  220. {
  221.      /* 初始化 */
  222.      GUI_Init();
  223.       
  224.      /*
  225.       关于多缓冲和窗口内存设备的设置说明
  226.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  227.            WM_MULTIBUF_Enable(1);
  228.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  229.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  230.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  231.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  232.         4. 所有emWin例子默认是开启三缓冲。
  233.      */
  234.      WM_MULTIBUF_Enable(1);
  235.      /*
  236.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  237.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  238.      */
  239.     //TOUCH_Calibration();
  240.    
  241.      /* 初始化使用GUI以前,先将字库从SD卡中加载到SP FLASH里面 */
  242.      LoadFontLib();
  243.    
  244.      /* 调用此函数会自动的刷新桌面窗口 */
  245.      WM_SetDesktopColor(GUI_BLUE);
  246.      /* 创建对话框 */
  247.      GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
  248.    
  249.      while(1)
  250.      {
  251.          GUI_Delay(10);
  252.      }
  253. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-22 15:56:51 | 显示全部楼层
25.8   总结


    本章节为大家讲解的GB2312编码格式字体是可以用于项目实战的,对于习惯了GB2312编码的用户来说是个很好的选择。这种方式的字体可以存储到任何外部存储介质中。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-17 00:27 , Processed in 0.199738 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表