硬汉嵌入式论坛

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

[emWin教程入门篇] 【emWin实战教程V2.0】第23章  XBF格式全字库生成和使用方法(Unicode编

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

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



第23章      XBF格式全字库生成和使用方法(Unicode编码)



    本章节为大家讲解XBF格式全字库的生成和使用方法。XBF格式字库可以存储到任何外部存储介质中,带不带文件系统都没有关系,且XBF格式字体支持抗锯齿效果,显示大字体的时候效果非常棒。XBF格式字体也是用FontCvt生成的,编码为Unicode。本章节以SPI Flash为例给大家进行讲解(SPIFlash就是SPI接口的Flash存储芯片)。
    23.1  初学者重要提示
    23.2  XBF格式字体生成方法
    23.3 不同XBF格式字体的合并方法
    23.4  XBF格式字体使用方法
    23.5 实验例程说明(RTOS)
    23.6 实验例程说明(裸机)
    23.7 总结



23.1  初学者重要提示


1、本章节配套的例子是将XBF格式字库烧写到不带文件系统的SPI Flash里面进行测试,效果比较好,也比较流畅。实际项目切不可给SPI Flash加上文件系统后使用XBF格式字体,否则会比较卡顿。
2、既然用到了SPI Flash,就需要驱动SPI Flash,本教程配套的例子是通过两个文件bsp_spi_bus.cbsp_spi_flash.c文件实现。
3、emWin官方提供的字体生成软件FontCvt不支持GB编码,所以只能使用FontCvt支持的Unicode编码。
4、这个字体小工具必须得使用STemWin软件包里面的,SEGGER官网下载的和MDK安装目录里面带的都是评估版
5、教程中让大家将要显示汉字的C文件转换为UTF-8编码,指的是将这个汉字所在的C文件转换为UTF-8编码,这点要切记,详情请看第22章的22.4小节说明。
6、XBF格式所有API函数在emWin手册中都有讲解,下图是中文版手册里面API函数的位置
23.1.png


下图是英文版手册里面API函数的位置:
23.2.png
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-19 16:08:12 | 显示全部楼层
23.2 XBF格式字体生成方法


    下面以生成16点阵,宋体为例来说明使用FontCvt生成XBF格式字体的方法。
第1步:打开字体生成软件FontCvt,选择字体类型Standard,编码选择16bit Unicode。
23.3.png

点击OK后,弹出如下窗口:
23.4.png

再点击确定后弹出FontCvt界面变成如下效果:
23.5.png

第2步:点击File->Save As
23.6.png

弹出如下窗口:
23.7.png

生成字体的过程中,左下角会有一个Unicode编码值从0x0000开始递增的过程,转换结束后显示Ready。
23.8.png

此时桌面就会生成XBF字库了。如果要生成的点阵字体比较大,此过程比较慢。本次转换生成的文件如下:
23.9.png

同样的方法再生成24点阵和32点阵的字体:
23.10.png

本章节配套的例子把这三种生成的字体都进行了测试。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-19 16:09:50 | 显示全部楼层
23.3 不同XBF格式字体文件的合并方法


    本小节讲解如何将上面小节生成的三种点阵字体合并成一个bin文件。合并成一个文件比较有实际意义,本章节配套的例子是将三种点阵字体都加载到SPIFlash里面,合并成一个bin文件后,加载一次就可以了。
第1步:登陆网址http://www.armbbs.cn/forum.php?mod=viewthread&tid=8627 下载小软件--->文件合并助手。
第2步:打开文件合并助手,加载本章23.2小节生成的三种字体
23.11.png

添加字库后,效果如下:
23.12.png

输出窗口已经自动生成了对应字体的首地址。这个地址要保存好,后面要用到。
第3步:点击右下角的合并,会弹出一个窗口
23.13.png


点击保存后,桌面后生成一个font.bin的文件:
23.14.png

注意,合并后的这个文件不要超过8MB,因为本教程配套板子的SPI Flash大小是8MB。这个文件的实际大小大约是7.89MB,没有超过8MB。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-19 16:17:08 | 显示全部楼层
23.4  XBF格式字体使用方法


    XBF格式字体的使用通过下面五步就可以实现:
第1步:定义16点阵,24点阵和32点阵的XBF格式字体
  1. /* 宋体16点阵定义 */
  2. #define   XBF_Font16BaseAdd    0x00000000
  3. GUI_XBF_DATA XBF_Data16;
  4. GUI_FONT     XBF_Font16;
  5. void         *Fontfile16;
  6. /* 宋体24点阵定义 */
  7. #define   XBF_Font24BaseAdd    0x0015B7B6
  8. GUI_XBF_DATA XBF_Data24;
  9. GUI_FONT     XBF_Font24;
  10. void         *Fontfile24;
  11. /* 宋体32点阵定义 */
  12. #define   XBF_Font32BaseAdd    0x003CEF64
  13. GUI_XBF_DATA XBF_Data32;
  14. GUI_FONT     XBF_Font32;
  15. void         *Fontfile32;
复制代码
每个字体都是三个变量和一个宏定义,宏定义用来设置字体的首地址,也就是23.3小节时给大家强调的。
23.15.png

另外三个变量的定义是创建XBF格式字体必须的,变量名可以任意定义,但是这三个变量不能少。其中指针类型变量void *Fontfile16,void *Fontfile24和void *Fontfile32都没有用到,如果使用了文件系统就用到了,这三个变量是用来定义文件系统变量的,比如使用FatFS文件系统,这三个变量就应该修改为FIL Fontfile16,FIL Fontfile24和FIL Fontfile32。
第2步:创建16点阵,24点阵和32点阵的XBF格式字体
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: _cbGetData16
  4. *    功能说明: XBF字体的回调函数, 16点阵
  5. *    形    参: Off      - 地址偏移
  6. *             NumBytes - 需要读出的字节数
  7. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  8. *             pBuffer  - 获取字体的点阵数据
  9. *    返 回 值: 0 表示成功 1 表示失败
  10. *********************************************************************************************************
  11. */
  12. static int _cbGetData16(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  13. {   
  14.      /* 读取点阵数据 */
  15.      sf_ReadBuffer(pBuffer, XBF_Font16BaseAdd + Off, NumBytes);
  16.      return 0;
  17. }
  18. /*
  19. *********************************************************************************************************
  20. *    函 数 名: _cbGetData24
  21. *    功能说明: XBF字体的回调函数, 24点阵
  22. *    形    参: Off      - 地址偏移
  23. *             NumBytes - 需要读出的字节数
  24. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  25. *             pBuffer  - 获取字体的点阵数据
  26. *    返 回 值: 0 表示成功 1 表示失败
  27. *********************************************************************************************************
  28. */
  29. static int _cbGetData24(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  30. {   
  31.      /* 读取点阵数据 */
  32.      sf_ReadBuffer(pBuffer, XBF_Font24BaseAdd + Off, NumBytes);
  33.      return 0;
  34. }
  35. /*
  36. *********************************************************************************************************
  37. *    函 数 名: _cbGetData32
  38. *    功能说明: XBF字体的回调函数, 32点阵
  39. *    形    参: Off      - 地址偏移
  40. *             NumBytes - 需要读出的字节数
  41. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  42. *             pBuffer  - 获取字体的点阵数据
  43. *    返 回 值: 0 表示成功 1 表示失败
  44. *********************************************************************************************************
  45. */
  46. static int _cbGetData32(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  47. {   
  48.      /* 读取点阵数据 */
  49.      sf_ReadBuffer(pBuffer, XBF_Font32BaseAdd + Off, NumBytes);
  50.      return 0;
  51. }
  52. /*
  53. *********************************************************************************************************
  54. *    函 数 名: GUI_SetXBF
  55. *    功能说明: 创建XBF字体
  56. *    形    参: 无
  57. *    返 回 值: 无
  58. *********************************************************************************************************
  59. */
  60. static void GUI_SetXBF(void)
  61. {
  62.      /* 创建16点阵字体 */
  63.      GUI_XBF_CreateFont(&XBF_Font16,           /* GUI_FONT类型变量     */
  64.                         &XBF_Data16,          /* GUI_XBF_DATA类型变量 */
  65.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  66.                         _cbGetData16,         /* 回调函数             */
  67.                         &Fontfile16);         /* 回调函数参数         */
  68.    
  69.      /* 创建24点阵字体 */
  70.      GUI_XBF_CreateFont(&XBF_Font24,           /* GUI_FONT类型变量     */
  71.                         &XBF_Data24,          /* GUI_XBF_DATA类型变量 */
  72.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  73.                         _cbGetData24,         /* 回调函数             */
  74.                         &Fontfile24);         /* 回调函数参数         */
  75.    
  76.      /* 创建32点阵字体 */
  77.      GUI_XBF_CreateFont(&XBF_Font32,           /* GUI_FONT类型变量     */
  78.                         &XBF_Data32,          /* GUI_XBF_DATA类型变量 */
  79.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  80.                         _cbGetData32,         /* 回调函数             */
  81.                         &Fontfile32);         /* 回调函数参数         */
  82. }
复制代码
创建XBF字体要用到函数:GUI_XBF_CreateFont,关于这个函数有必要说说,函数的原型如下:
  1. int GUI_XBF_CreateFont(GUI_FONT * pFont,
  2.                        GUI_XBF_DATA * pXBF_Data,
  3.                        const GUI_XBF_TYPE * pFontType,
  4.                        GUI_XBF_GET_DATA_FUNC * pfGetData,
  5.                        void * pVoid);
复制代码
(1)第1参数和第2个参数比较好理解,填写我们前面定义的变量就行。
(2)第3个参数要特别注意,参数类型一定要跟FontCvt创建时的字体类型对应。此参数有以下五种类型。
    GUI_XBF_TYPE_PROP
    GUI_XBF_TYPE_PROP_EXT
    GUI_XBF_TYPE_PROP_FRM
    GUI_XBF_TYPE_PROP_AA2_EXT
    GUI_XBF_TYPE_PROP_AA4_EXT
    而FontCvt创建的时候有以下七种类型:
23.16.png


    对应关系是
    GUI_XBF_TYPE_PROP = Standard
    GUI_XBF_TYPE_PROP_EXT = Extended
    GUI_XBF_TYPE_PROP_FRM = Extended,framed
    GUI_XBF_TYPE_PROP_AA2_EXT = Extended,antialiased,2bpp
    GUI_XBF_TYPE_PROP_AA4_EXT = Extended,antialiased,4bpp
    初学者使用的时候,一定要注意这个问题。另外要注意,字体类型antialiased,2bpp和antialiased,4bpp是不支持XBF格式字体的。
(3)第4步是回调函数,用户要在这个回调函数里面实现XBF字体点阵数据的读取,这里是从SPI Flash中读取点阵数据的。
(4)第5个参数是回调函数的一个形参,如果XBF文件是存储到不带文件系统的的存储介质中,这个参数是用不到的,如果带文件系统的话,这个参数是要用到的。实际项目中,不推荐将XBF字体存储到带文件系统的存储介质中,实际测试发现,稍大点的字体都会使得界面效果比较卡顿,不实用。如果进一步了解的话,参考emWin教程V1.0版本里面的第20章配套的例子,那个例子是将XBF字体存到SD卡中并使用文件系统Fatfs进行访问的,地址:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=2932
第3步:将23.3小节生成的font.bin文件存储到SPI Flash中,我们这里在电脑端将font.bin文件存储到SD卡中,然后开发板上电后将其从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[32];
  16.    
  17.      /* 清屏 */
  18.      GUI_SetBkColor(GUI_BLUE);
  19.      GUI_Clear();
  20.    
  21.      /* 设置字体 */
  22.      GUI_SetFont(&GUI_FontSong16);
  23.     y = 0;
  24.      /* 第1步:显示操作说明 ***************************************************************/
  25.      GUI_DispStringAt("SPI FLASH中存储字库实验", 0, y);
  26.      y += 16;
  27.    
  28.      GUI_DispStringAt("1. 使用前保证SD卡中已经放入字库文件font.bin", 0, y);
  29.      y += 16;
  30.    
  31.      GUI_DispStringAt("2. SD卡中不放入字库文件,无法将其复制到板载SPI FLASH中", 0, y);
  32.      y += 16;
  33.    
  34.      /* 等待10s后开始进行复制,方便客户看屏幕上的显示信息 */
  35.      for(i = 0; i < 11; i++)
  36.      {
  37.          sprintf(cDispBuf, "3. 10秒后开始复制, 还剩余%d秒 ", 10 - i);
  38.          GUI_DispStringAt(cDispBuf, 0, y);
  39.          GUI_Delay(1000);
  40.      }
  41.      y += 16;
  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文件打开失败", 0, y);
  49.          y += 16;
  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("复制失败                  ", 0, y);
  70.               break;
  71.          }
  72.         
  73.           /* 显示复制进度 */
  74.          Count = Count + 1;
  75.          FinishPecent = (float)(Count* g_tSF.PageSize) / file.fsize;
  76.          sprintf(cDispBuf, "当前完成复制:%02d%%", (uint8_t)(FinishPecent*100));
  77.          GUI_DispStringAt(cDispBuf, 0, y);
  78.      }
  79.    
  80.      /* 等待1秒后开始进去emWin主界面 */
  81.      GUI_Delay(1000);
  82. }
复制代码
第4步:加载到SPI Flash后,使用就比较简单了。
    用户只需调用函数GUI_UC_SetEncodeUTF8()使能UTF-8编码就可以使用XBF格式的字体了,比如设置按钮的字体,调用如下设置函数即可。
        BUTTON_SetFont(hWin,  &XBF_Font32);  /* hWin是按钮的句柄 */
第5步:最后一步切不可忘记设置汉字显示所在源文件的编码类型,具体MDK和IAR的设置方法请看第22章的22.4小节(本章节配套的例子也是设置的MainTask,c文件),这一步绝对不可以省略。
    通过这五步就实现XBF格式字体的显示了。另外还要注意一点,默认情况下,创建XB格式字体,每个字符的点阵数据最大值限制为200字节,可以满足大部分要求。如果加载使用更多字节的字符,通过在文件GUIConf.h添加以下宏定义可修改默认值:
        #define GUI_MAX_XBF_BYTES  500   /* 重新设置支持的最大字节数 */
        默认的定义在文件GUI_ConfDefaults.h文件里面:
        #ifndef   GUI_MAX_XBF_BYTES
            #defineGUI_MAX_XBF_BYTES 200
        #endif
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-19 16:22:11 | 显示全部楼层
23.5   实验例程说明(RTOS)


配套例子:
     V6-528_STemWin实验_XBF格式全字库的生成和使用方法,Unicode编码(RTOS)
实验目的:
    1.     学习emWin的XBF格式全字库的生成和使用方法,Unicode编码。
    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.     宋体16点阵,24点阵,32点阵的unicode编码完整字体。
字库存储方式:
    1.     字库存储到SPI FLASH里面。
实验步骤:
    1.     将字库文件font.bin放到SD卡根目录中,系统上电后会将其加载到SPI FLASH里面。
    2.     板子上电后会有一个加载进度指示,存储到SPI FLASH成功后会显示一个对话框。
    3.     字体文件为7.89MB,SPI FLASH为8MB,加载过程稍有些慢,请耐心等待。
实验注意:
    1.     实验所需的字库文件font.bin已经存储到本工程的Doc文件夹下,使用此例子前,请务必将这个文件存储到SD卡根目录中,并将SD卡插到开发板上面。
μCOS-III任务调试信息(按K1按键,串口打印):
23.17.png

STemWin界面显示效果:
    800*480分辨率界面效果。
23.18.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. extern GUI_CONST_STORAGE GUI_FONT GUI_FontSong16;
  9. /*
  10. *********************************************************************************************************
  11. *                                      定义XBF格式字体
  12. *********************************************************************************************************
  13. */
  14. /* 宋体16点阵定义 */
  15. #define   XBF_Font16BaseAdd    0x00000000
  16. GUI_XBF_DATA XBF_Data16;
  17. GUI_FONT     XBF_Font16;
  18. void         *Fontfile16;
  19. /* 宋体24点阵定义 */
  20. #define   XBF_Font24BaseAdd    0x0015B7B6
  21. GUI_XBF_DATA XBF_Data24;
  22. GUI_FONT     XBF_Font24;
  23. void         *Fontfile24;
  24. /* 宋体32点阵定义 */
  25. #define   XBF_Font32BaseAdd    0x003CEF64
  26. GUI_XBF_DATA XBF_Data32;
  27. GUI_FONT     XBF_Font32;
  28. void         *Fontfile32;
  29. uint8_t tempbuf[4096];  /* 从SD卡读取数据的缓冲 */
  30. /*
  31. *********************************************************************************************************
  32. *    函 数 名: _cbGetData16
  33. *    功能说明: XBF字体的回调函数, 16点阵
  34. *    形    参: Off      - 地址偏移
  35. *             NumBytes - 需要读出的字节数
  36. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  37. *             pBuffer  - 获取字体的点阵数据
  38. *    返 回 值: 0 表示成功 1 表示失败
  39. *********************************************************************************************************
  40. */
  41. static int _cbGetData16(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  42. {   
  43.      /* 读取点阵数据 */
  44.      sf_ReadBuffer(pBuffer, XBF_Font16BaseAdd + Off, NumBytes);
  45.      return 0;
  46. }
  47. /*
  48. *********************************************************************************************************
  49. *    函 数 名: _cbGetData24
  50. *    功能说明: XBF字体的回调函数, 24点阵
  51. *    形    参: Off      - 地址偏移
  52. *             NumBytes - 需要读出的字节数
  53. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  54. *             pBuffer  - 获取字体的点阵数据
  55. *    返 回 值: 0 表示成功 1 表示失败
  56. *********************************************************************************************************
  57. */
  58. static int _cbGetData24(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  59. {   
  60.      /* 读取点阵数据 */
  61.      sf_ReadBuffer(pBuffer, XBF_Font24BaseAdd + Off, NumBytes);
  62.      return 0;
  63. }
  64. /*
  65. *********************************************************************************************************
  66. *    函 数 名: _cbGetData32
  67. *    功能说明: XBF字体的回调函数, 32点阵
  68. *    形    参: Off      - 地址偏移
  69. *             NumBytes - 需要读出的字节数
  70. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  71. *             pBuffer  - 获取字体的点阵数据
  72. *    返 回 值: 0 表示成功 1 表示失败
  73. *********************************************************************************************************
  74. */
  75. static int _cbGetData32(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  76. {   
  77.      /* 读取点阵数据 */
  78.      sf_ReadBuffer(pBuffer, XBF_Font32BaseAdd + Off, NumBytes);
  79.      return 0;
  80. }
  81. /*
  82. *********************************************************************************************************
  83. *    函 数 名: GUI_SetXBF
  84. *    功能说明: 创建XBF字体
  85. *    形    参: 无
  86. *    返 回 值: 无
  87. *********************************************************************************************************
  88. */
  89. static void GUI_SetXBF(void)
  90. {
  91.      /* 创建16点阵字体 */
  92.      GUI_XBF_CreateFont(&XBF_Font16,           /* GUI_FONT类型变量     */
  93.                          &XBF_Data16,          /* GUI_XBF_DATA类型变量 */
  94.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  95.                         _cbGetData16,         /* 回调函数             */
  96.                         &Fontfile16);         /* 回调函数参数         */
  97.    
  98.      /* 创建24点阵字体 */
  99.      GUI_XBF_CreateFont(&XBF_Font24,          /* GUI_FONT类型变量     */
  100.                         &XBF_Data24,          /* GUI_XBF_DATA类型变量 */
  101.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  102.                         _cbGetData24,         /* 回调函数             */
  103.                         &Fontfile24);         /* 回调函数参数         */
  104.    
  105.      /* 创建32点阵字体 */
  106.      GUI_XBF_CreateFont(&XBF_Font32,           /* GUI_FONT类型变量     */
  107.                         &XBF_Data32,          /* GUI_XBF_DATA类型变量 */
  108.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  109.                         _cbGetData32,         /* 回调函数             */
  110.                         &Fontfile32);         /* 回调函数参数         */
  111. }
  112. /*
  113. *********************************************************************************************************
  114. *                                                       对话框信息
  115. *********************************************************************************************************
  116. */
  117. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  118.     { FRAMEWIN_CreateIndirect,  "安富莱电子",     0,          0,  0,  480, 272,FRAMEWIN_CF_MOVEABLE, 0},
  119.      { BUTTON_CreateIndirect,    "安富莱电子",     GUI_ID_BUTTON0,  10, 150, 400, 50, 0, 0},
  120.     { TEXT_CreateIndirect,      "安富莱电子AaAa-16点阵半角全角",   GUI_ID_TEXT1,   0, 40, 480, 33, 0,0},
  121.     { TEXT_CreateIndirect,      "安富莱电子AaAa-24点阵半角全角",   GUI_ID_TEXT2,   0, 70, 480, 72, 0,0},
  122.      { TEXT_CreateIndirect,      "安富莱电子AaAa-32点阵半全角",     GUI_ID_TEXT3,   0, 100, 480, 72, 0,0},
  123. };
  124. /*
  125. *********************************************************************************************************
  126. *    函 数 名: PaintDialog
  127. *    功能说明: 重绘
  128. *    形    参:pMsg  消息指针
  129. *    返 回 值: 无
  130. *********************************************************************************************************
  131. */
  132. void PaintDialog(WM_MESSAGE * pMsg)
  133. {
  134. }
  135. /*
  136. *********************************************************************************************************
  137. *    函 数 名: InitDialog
  138. *    功能说明: 对话框初始化
  139. *    形    参: pMsg 消息指针
  140. *    返 回 值: 无
  141. *********************************************************************************************************
  142. */
  143. void InitDialog(WM_MESSAGE * pMsg)
  144. {
  145.     WM_HWIN hWin = pMsg->hWin;
  146.    
  147.      //
  148.     // 框架窗口设置
  149.     //  
  150.     FRAMEWIN_SetFont(hWin,&XBF_Font24);
  151.     FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
  152.     FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);
  153.     FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);
  154.     FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);
  155.     FRAMEWIN_SetTitleHeight(hWin,35);
  156.    
  157.      //
  158.     // 按钮控件设置
  159.     //
  160.     BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&XBF_Font32);
  161.    
  162.     //
  163.     // 文本控件设置
  164.     //
  165.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_RED);
  166.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&XBF_Font16);
  167.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
  168.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&XBF_Font24);
  169.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT3), GUI_ORANGE);
  170.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&XBF_Font32);
  171.    
  172. }
  173. /*
  174. *********************************************************************************************************
  175. *    函 数 名: _cbCallback
  176. *    功能说明: 对话框回调函数
  177. *    形    参: 无
  178. *    返 回 值: 无
  179. *********************************************************************************************************
  180. */
  181. static void _cbCallback(WM_MESSAGE * pMsg)
  182. {
  183.     int NCode, Id;
  184.     WM_HWIN hWin = pMsg->hWin;
  185.     switch (pMsg->MsgId)
  186.     {
  187.         case WM_PAINT:
  188.             PaintDialog(pMsg);
  189.             break;
  190.         
  191.         case WM_INIT_DIALOG:
  192.             InitDialog(pMsg);
  193.             break;
  194.         
  195.         case WM_KEY:
  196.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  197.             {
  198.                 case GUI_KEY_ESCAPE:
  199.                     GUI_EndDialog(hWin, 1);
  200.                     break;
  201.                 case GUI_KEY_ENTER:
  202.                     GUI_EndDialog(hWin, 0);
  203.                     break;
  204.             }
  205.             break;
  206.             
  207.         case WM_NOTIFY_PARENT:
  208.             Id = WM_GetId(pMsg->hWinSrc);
  209.             NCode = pMsg->Data.v;      
  210.             switch (Id)
  211.             {
  212.                 case GUI_ID_OK:
  213.                     if(NCode==WM_NOTIFICATION_RELEASED)
  214.                         GUI_EndDialog(hWin, 0);
  215.                     break;
  216.                      
  217.                 case GUI_ID_CANCEL:
  218.                     if(NCode==WM_NOTIFICATION_RELEASED)
  219.                         GUI_EndDialog(hWin, 0);
  220.                     break;
  221.             }
  222.             break;
  223.             
  224.         default:
  225.             WM_DefaultProc(pMsg);
  226.     }
  227. }
  228. /*
  229. *********************************************************************************************************
  230. *    函 数 名: LoadFontLib()
  231. *    功能说明: 从SD卡中加载字库文件到SPI FLASH
  232. *    形    参: 无      
  233. *    返 回 值: 无
  234. *********************************************************************************************************
  235. */
  236. void LoadFontLib(void)
  237. {
  238.      float FinishPecent;
  239.     uint32_t Count = 0;
  240.      uint16_t y, i;
  241.      uint8_t ucState;
  242.      char cDispBuf[32];
  243.    
  244.      /* 清屏 */
  245.      GUI_SetBkColor(GUI_BLUE);
  246.      GUI_Clear();
  247.    
  248.      /* 设置字体 */
  249.      GUI_SetFont(&GUI_FontSong16);
  250.     y = 0;
  251.      /* 第1步:显示操作说明 ***************************************************************/
  252.      GUI_DispStringAt("SPI FLASH中存储字库实验", 0, y);
  253.      y += 16;
  254.    
  255.      GUI_DispStringAt("1. 使用前保证SD卡中已经放入字库文件font.bin", 0, y);
  256.      y += 16;
  257.    
  258.      GUI_DispStringAt("2. SD卡中不放入字库文件,无法将其复制到板载SPI FLASH中", 0, y);
  259.      y += 16;
  260.    
  261.      /* 等待10s后开始进行复制,方便客户看屏幕上的显示信息 */
  262.      for(i = 0; i < 11; i++)
  263.      {
  264.          sprintf(cDispBuf, "3. 10秒后开始复制, 还剩余%d秒 ", 10 - i);
  265.          GUI_DispStringAt(cDispBuf, 0, y);
  266.          GUI_Delay(1000);
  267.      }
  268.      y += 16;
  269.    
  270.    
  271.      /* 第2步:打开文件 ***************************************************************/
  272.      result = f_open(&file, "font.bin", FA_OPEN_EXISTING | FA_READ);
  273.      if (result !=  FR_OK)
  274.      {
  275.          GUI_DispStringAt("font.bin文件打开失败", 0, y);
  276.          y += 16;
  277.      }
  278.      /* 第3步:复制SD卡中字库文件font.bin到SPI FLASH **********************************/
  279.      for(;;)
  280.      {
  281.           /* 读取一个扇区的数据到buf */
  282.          result = f_read(&file, &tempbuf, g_tSF.PageSize, &bw);
  283.         
  284.          /* 读取出错或者读取完毕,退出 */
  285.          if ((result != FR_OK)||bw == 0)
  286.          {
  287.               break;
  288.          }
  289.         
  290.          /* 写数据到SPI FLASH */
  291.          ucState = sf_WriteBuffer(tempbuf, Count*g_tSF.PageSize, g_tSF.PageSize);
  292.         
  293.          /* 如果返回0,表示复制失败 */
  294.          if(ucState == 0)
  295.          {
  296.               GUI_DispStringAt("复制失败                  ", 0, y);
  297.               break;
  298.          }
  299.         
  300.           /* 显示复制进度 */
  301.          Count = Count + 1;
  302.          FinishPecent = (float)(Count* g_tSF.PageSize) / file.fsize;
  303.          sprintf(cDispBuf, "当前完成复制:%02d%%", (uint8_t)(FinishPecent*100));
  304.          GUI_DispStringAt(cDispBuf, 0, y);
  305.      }
  306.    
  307.      /* 等待1秒后开始进去emWin主界面 */
  308.      GUI_Delay(1000);
  309. }
  310. /*
  311. *********************************************************************************************************
  312. *    函 数 名: MainTask
  313. *    功能说明: GUI主函数
  314. *    形    参: 无
  315. *    返 回 值: 无
  316. *********************************************************************************************************
  317. */
  318. void MainTask(void)
  319. {
  320.      /* 初始化 */
  321.      GUI_Init();
  322.       
  323.      /*
  324.       关于多缓冲和窗口内存设备的设置说明
  325.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  326.            WM_MULTIBUF_Enable(1);
  327.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  328.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  329.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  330.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  331.         4. 所有emWin例子默认是开启三缓冲。
  332.      */
  333.      WM_MULTIBUF_Enable(1);
  334.    
  335.      /*
  336.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  337.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  338.      */
  339.     //TOUCH_Calibration();
  340.      /* 使能UTF-8编码 */   
  341.      GUI_UC_SetEncodeUTF8();
  342.    
  343.      /* 将字库从SD卡中加载到SP FLASH里面,加载一次即可,以后使用注释掉此函数 */
  344.      LoadFontLib();
  345.    
  346.      /* 创建XBF字体 */
  347.     GUI_SetXBF();
  348.    
  349.      /* 调用此函数会自动的刷新桌面窗口 */
  350.      WM_SetDesktopColor(GUI_BLUE);
  351.      /* 创建对话框 */
  352.      GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
  353.    
  354.      while(1)
  355.      {
  356.          GUI_Delay(10);
  357.      }
  358. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-19 16:29:24 | 显示全部楼层
23.6 实验例程说明(裸机)


配套例子:
    V6-529_STemWin实验_XBF格式全字库的生成和使用方法,Unicode编码(裸机)
实验目的:
    1.     学习emWin的XBF格式全字库的生成和使用方法,Unicode编码。
    2.     emWin功能的实现在MainTask.·c文件里面。
支持点阵:
    1.     宋体16点阵,24点阵,32点阵的Unicode编码完整字体。
字库存储方式:
    1.     字库存储到SPI FLASH里面。
实验步骤:
    1.     将字库文件font.bin放到SD卡根目录中,系统上电后会将其加载到SPI FLASH里面。
    2.     板子上电后会有一个加载进度指示,存储到SPI FLASH成功后会显示一个对话框。
    3.     字体文件为7.89MB,SPI FLASH为8MB,加载过程稍有些慢,请耐心等待。
实验注意:
    1. 实验所需的字库文件font.bin已经存储到本工程的Doc文件夹下,使用此例子前,请务必将这个文件存储到SD卡根目录中,并将SD卡插到开发板上面。
STemWin界面显示效果:
    800*480分辨率界面效果。
23.19.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文件中配置:
23.20.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. extern GUI_CONST_STORAGE GUI_FONT GUI_FontSong16;
  9. /*
  10. *********************************************************************************************************
  11. *                                      定义XBF格式字体
  12. *********************************************************************************************************
  13. */
  14. /* 宋体16点阵定义 */
  15. #define   XBF_Font16BaseAdd    0x00000000
  16. GUI_XBF_DATA XBF_Data16;
  17. GUI_FONT     XBF_Font16;
  18. void         *Fontfile16;
  19. /* 宋体24点阵定义 */
  20. #define   XBF_Font24BaseAdd    0x0015B7B6
  21. GUI_XBF_DATA XBF_Data24;
  22. GUI_FONT     XBF_Font24;
  23. void         *Fontfile24;
  24. /* 宋体32点阵定义 */
  25. #define   XBF_Font32BaseAdd    0x003CEF64
  26. GUI_XBF_DATA XBF_Data32;
  27. GUI_FONT     XBF_Font32;
  28. void         *Fontfile32;
  29. uint8_t tempbuf[4096];  /* 从SD卡读取数据的缓冲 */
  30. /*
  31. *********************************************************************************************************
  32. *    函 数 名: _cbGetData16
  33. *    功能说明: XBF字体的回调函数, 16点阵
  34. *    形    参: Off      - 地址偏移
  35. *             NumBytes - 需要读出的字节数
  36. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  37. *             pBuffer  - 获取字体的点阵数据
  38. *    返 回 值: 0 表示成功 1 表示失败
  39. *********************************************************************************************************
  40. */
  41. static int _cbGetData16(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  42. {   
  43.      /* 读取点阵数据 */
  44.      sf_ReadBuffer(pBuffer, XBF_Font16BaseAdd + Off, NumBytes);
  45.      return 0;
  46. }
  47. /*
  48. *********************************************************************************************************
  49. *    函 数 名: _cbGetData24
  50. *    功能说明: XBF字体的回调函数, 24点阵
  51. *    形    参: Off      - 地址偏移
  52. *             NumBytes - 需要读出的字节数
  53. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  54. *             pBuffer  - 获取字体的点阵数据
  55. *    返 回 值: 0 表示成功 1 表示失败
  56. *********************************************************************************************************
  57. */
  58. static int _cbGetData24(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  59. {   
  60.      /* 读取点阵数据 */
  61.      sf_ReadBuffer(pBuffer, XBF_Font24BaseAdd + Off, NumBytes);
  62.      return 0;
  63. }
  64. /*
  65. *********************************************************************************************************
  66. *    函 数 名: _cbGetData32
  67. *    功能说明: XBF字体的回调函数, 32点阵
  68. *    形    参: Off      - 地址偏移
  69. *             NumBytes - 需要读出的字节数
  70. *             pVoid    - 指针变量,一般用于带文件系统时的FIL类型变量
  71. *             pBuffer  - 获取字体的点阵数据
  72. *    返 回 值: 0 表示成功 1 表示失败
  73. *********************************************************************************************************
  74. */
  75. static int _cbGetData32(U32 Off, U16 NumBytes, void * pVoid, void * pBuffer)
  76. {   
  77.      /* 读取点阵数据 */
  78.      sf_ReadBuffer(pBuffer, XBF_Font32BaseAdd + Off, NumBytes);
  79.      return 0;
  80. }
  81. /*
  82. *********************************************************************************************************
  83. *    函 数 名: GUI_SetXBF
  84. *    功能说明: 创建XBF字体
  85. *    形    参: 无
  86. *    返 回 值: 无
  87. *********************************************************************************************************
  88. */
  89. static void GUI_SetXBF(void)
  90. {
  91.      /* 创建16点阵字体 */
  92.      GUI_XBF_CreateFont(&XBF_Font16,           /* GUI_FONT类型变量     */
  93.                         &XBF_Data16,          /* GUI_XBF_DATA类型变量 */
  94.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  95.                         _cbGetData16,         /* 回调函数             */
  96.                         &Fontfile16);         /* 回调函数参数         */
  97.    
  98.      /* 创建24点阵字体 */
  99.      GUI_XBF_CreateFont(&XBF_Font24,          /* GUI_FONT类型变量     */
  100.                         &XBF_Data24,          /* GUI_XBF_DATA类型变量 */
  101.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  102.                         _cbGetData24,         /* 回调函数             */
  103.                         &Fontfile24);         /* 回调函数参数         */
  104.    
  105.      /* 创建32点阵字体 */
  106.      GUI_XBF_CreateFont(&XBF_Font32,           /* GUI_FONT类型变量     */
  107.                         &XBF_Data32,          /* GUI_XBF_DATA类型变量 */
  108.                         GUI_XBF_TYPE_PROP,    /* 字体类型             */
  109.                         _cbGetData32,         /* 回调函数             */
  110.                         &Fontfile32);         /* 回调函数参数         */
  111. }
  112. /*
  113. *********************************************************************************************************
  114. *                                                       对话框信息
  115. *********************************************************************************************************
  116. */
  117. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  118.     { FRAMEWIN_CreateIndirect,  "安富莱电子",     0,          0,  0,  480, 272,FRAMEWIN_CF_MOVEABLE, 0},
  119.      { BUTTON_CreateIndirect,    "安富莱电子",     GUI_ID_BUTTON0,  10, 150, 400, 50, 0, 0},
  120.     { TEXT_CreateIndirect,      "安富莱电子AaAa-16点阵半角全角",   GUI_ID_TEXT1,   0, 40, 480, 33, 0,0},
  121.     { TEXT_CreateIndirect,      "安富莱电子AaAa-24点阵半角全角",   GUI_ID_TEXT2,   0, 70, 480, 72, 0,0},
  122.      { TEXT_CreateIndirect,      "安富莱电子AaAa-32点阵半全角",     GUI_ID_TEXT3,   0, 100, 480, 72, 0,0},
  123. };
  124. /*
  125. *********************************************************************************************************
  126. *    函 数 名: PaintDialog
  127. *    功能说明: 重绘
  128. *    形    参:pMsg  消息指针
  129. *    返 回 值: 无
  130. *********************************************************************************************************
  131. */
  132. void PaintDialog(WM_MESSAGE * pMsg)
  133. {
  134. }
  135. /*
  136. *********************************************************************************************************
  137. *    函 数 名: InitDialog
  138. *    功能说明: 对话框初始化
  139. *    形    参: pMsg 消息指针
  140. *    返 回 值: 无
  141. *********************************************************************************************************
  142. */
  143. void InitDialog(WM_MESSAGE * pMsg)
  144. {
  145.     WM_HWIN hWin = pMsg->hWin;
  146.    
  147.      //
  148.     // 框架窗口设置
  149.     //  
  150.     FRAMEWIN_SetFont(hWin,&XBF_Font24);
  151.     FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
  152.     FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);
  153.     FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);
  154.     FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);
  155.     FRAMEWIN_SetTitleHeight(hWin,35);
  156.    
  157.      //
  158.     // 按钮控件设置
  159.     //
  160.     BUTTON_SetFont(WM_GetDialogItem(hWin,GUI_ID_BUTTON0),&XBF_Font32);
  161.    
  162.     //
  163.     // 文本控件设置
  164.     //
  165.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT1), GUI_RED);
  166.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT1),&XBF_Font16);
  167.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT2), GUI_BLUE);
  168.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT2),&XBF_Font24);
  169.      TEXT_SetTextColor(WM_GetDialogItem(hWin,GUI_ID_TEXT3), GUI_ORANGE);
  170.      TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT3),&XBF_Font32);
  171.    
  172. }
  173. /*
  174. *********************************************************************************************************
  175. *    函 数 名: _cbCallback
  176. *    功能说明: 对话框回调函数
  177. *    形    参: 无
  178. *    返 回 值: 无
  179. *********************************************************************************************************
  180. */
  181. static void _cbCallback(WM_MESSAGE * pMsg)
  182. {
  183.     int NCode, Id;
  184.     WM_HWIN hWin = pMsg->hWin;
  185.     switch (pMsg->MsgId)
  186.     {
  187.         case WM_PAINT:
  188.             PaintDialog(pMsg);
  189.             break;
  190.         
  191.         case WM_INIT_DIALOG:
  192.             InitDialog(pMsg);
  193.             break;
  194.         
  195.         case WM_KEY:
  196.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  197.             {
  198.                 case GUI_KEY_ESCAPE:
  199.                     GUI_EndDialog(hWin, 1);
  200.                     break;
  201.                 case GUI_KEY_ENTER:
  202.                     GUI_EndDialog(hWin, 0);
  203.                     break;
  204.             }
  205.             break;
  206.             
  207.         case WM_NOTIFY_PARENT:
  208.             Id = WM_GetId(pMsg->hWinSrc);
  209.             NCode = pMsg->Data.v;      
  210.             switch (Id)
  211.             {
  212.                 case GUI_ID_OK:
  213.                     if(NCode==WM_NOTIFICATION_RELEASED)
  214.                         GUI_EndDialog(hWin, 0);
  215.                     break;
  216.                      
  217.                 case GUI_ID_CANCEL:
  218.                     if(NCode==WM_NOTIFICATION_RELEASED)
  219.                         GUI_EndDialog(hWin, 0);
  220.                     break;
  221.             }
  222.             break;
  223.             
  224.         default:
  225.             WM_DefaultProc(pMsg);
  226.     }
  227. }
  228. /*
  229. *********************************************************************************************************
  230. *    函 数 名: LoadFontLib()
  231. *    功能说明: 从SD卡中加载字库文件到SPI FLASH
  232. *    形    参: 无      
  233. *    返 回 值: 无
  234. *********************************************************************************************************
  235. */
  236. void LoadFontLib(void)
  237. {
  238.      float FinishPecent;
  239.     uint32_t Count = 0;
  240.      uint16_t y, i;
  241.      uint8_t ucState;
  242.      char cDispBuf[32];
  243.    
  244.      /* 清屏 */
  245.      GUI_SetBkColor(GUI_BLUE);
  246.      GUI_Clear();
  247.    
  248.      /* 设置字体 */
  249.      GUI_SetFont(&GUI_FontSong16);
  250.     y = 0;
  251.      /* 第1步:显示操作说明 ***************************************************************/
  252.      GUI_DispStringAt("SPI FLASH中存储字库实验", 0, y);
  253.      y += 16;
  254.    
  255.      GUI_DispStringAt("1. 使用前保证SD卡中已经放入字库文件font.bin", 0, y);
  256.      y += 16;
  257.    
  258.      GUI_DispStringAt("2. SD卡中不放入字库文件,无法将其复制到板载SPI FLASH中", 0, y);
  259.      y += 16;
  260.    
  261.      /* 等待10s后开始进行复制,方便客户看屏幕上的显示信息 */
  262.      for(i = 0; i < 11; i++)
  263.      {
  264.          sprintf(cDispBuf, "3. 10秒后开始复制, 还剩余%d秒 ", 10 - i);
  265.          GUI_DispStringAt(cDispBuf, 0, y);
  266.          GUI_Delay(1000);
  267.      }
  268.      y += 16;
  269.    
  270.    
  271.      /* 第2步:打开文件 ***************************************************************/
  272.      result = f_open(&file, "font.bin", FA_OPEN_EXISTING | FA_READ);
  273.      if (result !=  FR_OK)
  274.      {
  275.          GUI_DispStringAt("font.bin文件打开失败", 0, y);
  276.          y += 16;
  277.      }
  278.      /* 第3步:复制SD卡中字库文件font.bin到SPI FLASH **********************************/
  279.      for(;;)
  280.      {
  281.           /* 读取一个扇区的数据到buf */
  282.          result = f_read(&file, &tempbuf, g_tSF.PageSize, &bw);
  283.         
  284.          /* 读取出错或者读取完毕,退出 */
  285.          if ((result != FR_OK)||bw == 0)
  286.          {
  287.               break;
  288.          }
  289.         
  290.          /* 写数据到SPI FLASH */
  291.          ucState = sf_WriteBuffer(tempbuf, Count*g_tSF.PageSize, g_tSF.PageSize);
  292.         
  293.          /* 如果返回0,表示复制失败 */
  294.          if(ucState == 0)
  295.          {
  296.               GUI_DispStringAt("复制失败                  ", 0, y);
  297.               break;
  298.          }
  299.         
  300.           /* 显示复制进度 */
  301.          Count = Count + 1;
  302.          FinishPecent = (float)(Count* g_tSF.PageSize) / file.fsize;
  303.          sprintf(cDispBuf, "当前完成复制:%02d%%", (uint8_t)(FinishPecent*100));
  304.          GUI_DispStringAt(cDispBuf, 0, y);
  305.      }
  306.    
  307.      /* 等待1秒后开始进去emWin主界面 */
  308.      GUI_Delay(1000);
  309. }
  310. /*
  311. *********************************************************************************************************
  312. *    函 数 名: MainTask
  313. *    功能说明: GUI主函数
  314. *    形    参: 无
  315. *    返 回 值: 无
  316. *********************************************************************************************************
  317. */
  318. void MainTask(void)
  319. {
  320.      /* 初始化 */
  321.      GUI_Init();
  322.       
  323.      /*
  324.       关于多缓冲和窗口内存设备的设置说明
  325.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  326.            WM_MULTIBUF_Enable(1);
  327.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  328.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  329.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  330.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  331.         4. 所有emWin例子默认是开启三缓冲。
  332.      */
  333.      WM_MULTIBUF_Enable(1);
  334.    
  335.      /*
  336.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  337.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  338.      */
  339.     //TOUCH_Calibration();
  340.      /* 使能UTF-8编码 */   
  341.      GUI_UC_SetEncodeUTF8();
  342.    
  343.      /* 将字库从SD卡中加载到SP FLASH里面,加载一次即可,以后使用注释掉此函数 */
  344.      LoadFontLib();
  345.    
  346.      /* 创建XBF字体 */
  347.     GUI_SetXBF();
  348.    
  349.      /* 调用此函数会自动的刷新桌面窗口 */
  350.      WM_SetDesktopColor(GUI_BLUE);
  351.      /* 创建对话框 */
  352.      GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
  353.    
  354.      while(1)
  355.      {
  356.          GUI_Delay(10);
  357.      }
  358. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-1-19 16:29:48 | 显示全部楼层
23.7总结


    本章节为大家讲解的XBF格式字体是可以用于项目实战的,望初学者务必掌握。项目中不限制将XBF格式字体存储到SPI Flash里面,存储到NOR Flash,SD卡,NAND Flash等也是可以的,只要速度满足要求即可,不过还是建议将其存储到无需文件系统的存储介质中,速度比较快。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-16 07:58 , Processed in 0.202082 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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