硬汉嵌入式论坛

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

[emWin教程入门篇] 【emWin实战教程V2.0】第62章    STemWin键盘输入(实体按键操

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

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





第62章    STemWin键盘输入(实体按键操作控件)


        本章节为大家讲解键盘输入设备或者类似键盘的外部输入设备来控制emWin。实际项目中,很多时候需要使用外部
小键盘来操作emWin界面,那么学好本章节的内容就尤其重要了,望初学者务必要掌握。
        62.1 初学者重要提示
        62.2 键盘编码基础知识
        62.3 键盘相关的API函数
        62.4 实体按键操作控件说明
        62.5 实验例程说明(RTOS)
        62.6 实验例程说明(裸机)
        62.7 总结
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-31 16:27:40 | 显示全部楼层
62.1  初学者重要提示

1、初学者爱问的问题简单汇总:
        问题1:为什么使用函数GUI_SendKeyMsg发送消息后,控件没有反应?
        答:首先要保证控件被聚焦,还有就是查看此控件是否支持键盘消息。
2、 键盘输入的所有API函数在emWin手册中都有讲解,下图是中文版手册里面API函数位置:
2.1.png


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

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-31 16:28:54 | 显示全部楼层
62.2 键盘编码基础知识


        键盘输入设备或者类似键盘的外部输入设备使用ASCII字符编码,以便区分不同的字符。STemWin 同时定义了其他虚拟键盘操作的字符编码,这些编码如下表所示:
2.3.png

通过上面的编码可以看出,基本与我们在电脑端使用的键盘编码是一样的。GUI.h文件中具体定义的键值编码如下:
  1. /*********************************************************************
  2. *
  3. *       GUI_KEY_...
  4. *
  5. * These ID values are basically meant to be used with widgets
  6. * Note that we have chosen the values to be close to existing
  7. * "standards", so do not change them unless forced to.
  8. *
  9. */
  10. #define GUI_KEY_BACKSPACE         8         /* ASCII: BACKSPACE Crtl-H */
  11. #define GUI_KEY_TAB               9         /* ASCII: TAB       Crtl-I */
  12. #define GUI_KEY_BACKTAB           10
  13. #define GUI_KEY_ENTER             13        /* ASCII: ENTER     Crtl-M */
  14. #define GUI_KEY_LEFT              16
  15. #define GUI_KEY_UP                17
  16. #define GUI_KEY_RIGHT             18
  17. #define GUI_KEY_DOWN              19
  18. #define GUI_KEY_HOME              23
  19. #define GUI_KEY_END               24
  20. #define GUI_KEY_SHIFT             25
  21. #define GUI_KEY_CONTROL           26
  22. #define GUI_KEY_ESCAPE            27        /* ASCII: ESCAPE    0x1b   */
  23. #define GUI_KEY_INSERT            29
  24. #define GUI_KEY_DELETE            30
  25. #define GUI_KEY_SPACE             32
  26. #define GUI_KEY_PGUP              33
  27. #define GUI_KEY_PGDOWN            34
  28. #define GUI_KEY_F1                40
  29. #define GUI_KEY_F2                41
复制代码
这些编码就是我们在前面所有的控件章节都有跟大家讲解的:控件支持的键盘反应。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-31 16:30:00 | 显示全部楼层
62.3 键盘相关的API函数


        驱动层,键盘消息处理函数有以下两个:
2.4.png

u  voidGUI_StoreKeyMsg(int Key, int Pressed)
        Key可以是任意扩展ASCII字符 (范围为0x20至0xFF)或者任意预定义的emWin虚拟键盘编码,PressedCnt = 0表示松开或者未按下的状态,PressedCnt > 0表示按下。
        该函数支持从中断服务程序调用。另外,STemWin的键盘输入管理器含有一个FIFO缓冲,默认情况下最多可以保存10个键盘事件,如果需要修改为其它大小,可以在GUIConf.h文件中设置宏定义:
                 #define  GUI_KEY_BUFFER_SIZE   10
注意一点,如果大家使用的emWin库没有将这个宏定义开放出来,即使配置了也是无效的,具体是否有效,需要大家去做实验验证。
u  voidGUI_SendKeyMsg(int Key, int Pressed)
        该函数把消息发送给聚焦的控件,如果没有控件被聚焦,此消息会被存储到键盘缓冲区。另外,该函数不支持从中断服务程序调用,其它方面与函数GUI_StoreKeyMsg是一样的。
-----------------------------------------
应用层有以下四个函数,这个几个函数都比较易学易用,大家参看官方手册即可(如果大家有印象的话,前面几个章节讲解官方的例子时,多次用到函数GUI_GetKey,其它三个很少用到):
2.5.png
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-31 16:31:49 | 显示全部楼层
62.4 实体按键操作控件说明


        有了前面两个小节的说明,实体按键操作控件比较容易,用户想要操作哪个控件,设置聚焦到那个控件即可,然后通过函数GUI_StoreKeyMsg或者GUI_SendKeyMsg发消息,此处使用的是函数GUI_SendKeyMsg。
        我们这里是利用开发板上面的实体按键来发消息:
2.6.png

检测到哪个按键被按下了,就在相应的按键消息里面通过函数GUI_SendKeyMsg发送键盘消息,具体实现代码如下:
  1. /*
  2. *********************************************************************************************************
  3. *    函 数 名: AppTaskUserIF
  4. *    功能说明: 按键消息处理
  5. *    形    参: p_arg 是在创建该任务时传递的形参
  6. *    返 回 值: 无
  7.      优 先 级: 4
  8. *********************************************************************************************************
  9. */
  10. static void AppTaskUserIF(void *p_arg)
  11. {
  12.      OS_ERR      err;
  13.      uint8_t  ucKeyCode;
  14.    
  15.      (void)p_arg;             /* 避免编译器报警 */
  16.    
  17.      while (1)
  18.      {      
  19.           ucKeyCode = bsp_GetKey();
  20.         
  21.          if(ucKeyCode != KEY_NONE)
  22.          {
  23.               switch (ucKeyCode)
  24.               {
  25.                    case KEY_DOWN_K1:           /* K1键按下 串口打印任务执行情况 */
  26.                        DispTaskInfo();
  27.                        break;
  28.                    case KEY_DOWN_K2:             /* K2键按下,向消息队列发送数据 */
  29.                        OSSemPost((OS_SEM *)&SEM_SYNCH,
  30.                                   (OS_OPT  )OS_OPT_POST_1,
  31.                                   (OS_ERR *)&err);
  32.                        break;
  33.                   
  34.                    case KEY_DOWN_K3:           /* K3键按下,实现TAB按键的功能*/
  35.                        GUI_SendKeyMsg(GUI_KEY_TAB, 1);
  36.                        break;
  37.                    case JOY_DOWN_U:            /* 摇杆UP键按下,实现删除光标后的字符 */
  38.                        GUI_SendKeyMsg(GUI_KEY_DELETE, 1);
  39.                        break;
  40.                    case JOY_DOWN_D:            /* 摇杆DOWN键按下,实现删除光标前的字符 */
  41.                        GUI_SendKeyMsg(GUI_KEY_BACKSPACE, 1);
  42.                        break;
  43.                    case JOY_DOWN_L:            /* 摇杆LEFT键按下,实现光标左移 */
  44.                        GUI_SendKeyMsg(GUI_KEY_LEFT, 1);
  45.                        break;
  46.                    case JOY_DOWN_R:            /* 摇杆RIGHT键按下,实现光标右移 */
  47.                        GUI_SendKeyMsg(GUI_KEY_RIGHT, 1);
  48.                        break;
  49.                    case JOY_DOWN_OK:           /* 摇杆OK键按下,主要给本工程界面的按钮发送此消息 */
  50.                        GUI_SendKeyMsg(GUI_KEY_ENTER, 1);
  51.                        break;
  52.                    default:
  53.                        /* 其它的键值不处理 */
  54.                        break;
  55.               }
  56.                   
  57.          }
  58.         
  59.          OSTimeDly(20, OS_OPT_TIME_DLY, &err);
  60.      }
  61. }
复制代码
如果大家使用的是其它类型的键盘输入设备,方法是一样的。对于emWin的界面,只要有被聚焦的控件,就可以发送相应的键盘消息给此控件。当然,不同的控件支持的键盘消息有所不同,比如本章节配套例子的部分代码:
  1. /*
  2. *********************************************************************************************************
  3. *                                         宏定义
  4. *********************************************************************************************************
  5. */
  6. #define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
  7. #define ID_EDIT_0   (GUI_ID_USER + 0x01)
  8. #define ID_EDIT_1   (GUI_ID_USER + 0x03)
  9. /*
  10. *********************************************************************************************************
  11. *                           GUI_WIDGET_CREATE_INFO类型数组
  12. *********************************************************************************************************
  13. */
  14. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
  15. {
  16.      { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 320, 240, 0, 0x64, 0 },
  17.      { EDIT_CreateIndirect, "Edit", ID_EDIT_0, 88, 27, 159, 29, 0, 0x64, 0 },
  18.      { EDIT_CreateIndirect, "Edit", ID_EDIT_1, 87, 73, 159, 30, 0, 0x64, 0 },
  19.      { BUTTON_CreateIndirect, "Button", GUI_ID_OK, 26, 139, 97, 31, 0, 0x0, 0 },
  20.      { BUTTON_CreateIndirect, "Button", GUI_ID_CANCEL, 179, 139, 100, 31, 0, 0x0, 0 },
  21. };
  22. /*
  23. *********************************************************************************************************
  24. *    函 数 名: _cbDialog
  25. *    功能说明: 对话框的回调函数
  26. *    形    参: pMsg 消息指针
  27. *    返 回 值: 无
  28. *********************************************************************************************************
  29. */
  30. static void _cbDialog(WM_MESSAGE * pMsg)
  31. {
  32.      int     NCode;
  33.      int     Id;
  34.      WM_HWIN hDlg;
  35.      WM_HWIN hItem;
  36.      hDlg = pMsg->hWin;
  37.      switch (pMsg->MsgId)
  38.      {
  39.          case WM_INIT_DIALOG:
  40.         
  41.              //
  42.               // 初始化框架窗口
  43.               //
  44.               hItem = pMsg->hWin;
  45.               FRAMEWIN_SetFont(hItem, GUI_FONT_24_ASCII);
  46.               FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
  47.               FRAMEWIN_SetText(hItem, "armfly");
  48.         
  49.               //
  50.               // 初始化编辑框控件
  51.               //
  52.               hItem = WM_GetDialogItem(pMsg->hWin, ID_EDIT_0);
  53.               EDIT_SetText(hItem, "www.armfly.com");
  54.               EDIT_SetTextAlign(hItem, GUI_TA_LEFT | GUI_TA_VCENTER);
  55.               EDIT_SetFont(hItem, GUI_FONT_16_ASCII);
  56.               EDIT_SetSel(hItem, 0, -1);
  57.             
  58.               //
  59.               // 初始化边框控件
  60.               //
  61.               hItem = WM_GetDialogItem(pMsg->hWin, ID_EDIT_1);
  62.               EDIT_SetText(hItem, "www.baidu.com");
  63.               EDIT_SetFont(hItem, GUI_FONT_16_ASCII);
  64.               EDIT_SetTextAlign(hItem, GUI_TA_LEFT | GUI_TA_VCENTER);
  65.               EDIT_SetSel(hItem, 0, -1);
  66.             
  67.               //
  68.               // 初始化按钮控件
  69.               //
  70.               hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_OK);
  71.               BUTTON_SetText(hItem, "OK");
  72.               BUTTON_SetFont(hItem, GUI_FONT_16_ASCII);
  73.             
  74.               //
  75.               // 初始化按钮控件
  76.               //
  77.               hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_CANCEL);
  78.               BUTTON_SetText(hItem, "Cancel");
  79.               BUTTON_SetFont(hItem, GUI_FONT_16_ASCII);
  80.               break;
  81.             
  82.           case WM_KEY:
  83.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  84.             {
  85.                    case GUI_KEY_ESCAPE:
  86.                     GUI_EndDialog(hDlg, 1);
  87.                     break;
  88.                   
  89.                 case GUI_KEY_ENTER:
  90.                     GUI_EndDialog(hDlg, 0);
  91.                     break;
  92.             }
  93.             break;
  94.             
  95.          case WM_NOTIFY_PARENT:
  96.               Id    = WM_GetId(pMsg->hWinSrc);
  97.               NCode = pMsg->Data.v;
  98.               switch(Id)
  99.               {
  100.                    /* 点击OK按钮,关闭对话框 */
  101.                    case GUI_ID_OK:
  102.                        switch(NCode)
  103.                        {
  104.                             case WM_NOTIFICATION_CLICKED:
  105.                                  break;
  106.                            
  107.                             case WM_NOTIFICATION_RELEASED:
  108.                                  GUI_EndDialog(hDlg, 0);
  109.                                  break;
  110.                        }
  111.                        break;
  112.    
  113.                    /* 点击CANCEL按钮,关闭对话框 */                     
  114.                    case GUI_ID_CANCEL:
  115.                        switch(NCode)
  116.                        {
  117.                             case WM_NOTIFICATION_CLICKED:
  118.                                  break;
  119.                            
  120.                             case WM_NOTIFICATION_RELEASED:
  121.                                  GUI_EndDialog(hDlg, 1);
  122.                                  break;
  123.                        }
  124.                        break;               
  125.               }
  126.               break;
  127.          default:
  128.               WM_DefaultProc(pMsg);
  129.      }
  130. }
复制代码
创建此对话框后的首次显示效果如下:
2.7.png


默认情况下,对话框创建后,系统会聚焦到对话框资源列表里面第一个支持聚焦的控件上(这点要特别注意)。具体到给每个控件发送键盘消息,大家可以使用本章节配套的例子在开发板上面实际操作下,另外,通过我们前面设置的按键K3发送GUI_KEY_TAB消息,按下K3按键后会切换聚焦到对话框资源列表中下一个支持聚焦的控件。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-31 16:38:07 | 显示全部楼层
62.5 实验例程说明(RTOS)


配套例子:
        V6-599_STemWin实验_键盘输入,实体按键操作控件(RTOS)
实验目的:
        1.     本实验主要学习实体按键操作控件的使用。
        2.     emWin功能的实现在MainTask.c文件里面。
实验内容:
        1.     K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
        2.     K2按键按下,实现截图功能,将图片以BMP格式保存到SD卡中。
        3.     针对本例子创建的界面,其余按键操作实现的功能如下,第4条到第9条。
        4.     K3按钮按下,实现控件聚焦的切换。
        5.     摇杆向上按,实现删除编辑框控件光标后的字符。
        6.     摇杆向下按,实现删除编辑框控件光标前的字符。
        7.     摇杆向左按,实现光标左移。
        8.     摇杆向右按,实现光标右移。
        9.     摇杆按下OK键,发送按键消息GUI_KEY_ENTER,如果当前聚焦到按钮控件上,发送此消息会关闭对话框。如果未聚焦到按钮控件上,发送消息GUI_KEY_ENTER会被对话框回调函数中WM_KEY消息所接受,同样也是实现关闭对话框功能。
        10.  各个任务实现的功能如下:
              App Task Start   任务:实现按键和触摸扫描。
              App Task MspPro任务 :实现截图功能,将图片以BMP格式保存到SD卡中。
              App Task UserIF  任务:按键消息处理。
              App Task COM   任务:暂未使用。
             App Task GUI    任务:GUI任务。
μCOS-III任务调试信息(按K1按键,串口打印):
2.8.png

STemWin界面显示效果:
        800*480分辨率界面效果。
2.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格式,且仅使用单图层。
程序设计:
任务栈大小分配:
        μ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.                    case KEY_DOWN_K2:             /* K2键按下,向消息队列发送数据 */
  166.                        OSSemPost((OS_SEM *)&SEM_SYNCH,
  167.                                   (OS_OPT  )OS_OPT_POST_1,
  168.                                   (OS_ERR *)&err);
  169.                        break;
  170.                   
  171.                    case KEY_DOWN_K3:           /* K3键按下,实现TAB按键的功能*/
  172.                        GUI_SendKeyMsg(GUI_KEY_TAB, 1);
  173.                        break;
  174.                    case JOY_DOWN_U:            /* 摇杆UP键按下,实现删除光标后的字符 */
  175.                        GUI_SendKeyMsg(GUI_KEY_DELETE, 1);
  176.                        break;
  177.                    case JOY_DOWN_D:            /* 摇杆DOWN键按下,实现删除光标前的字符 */
  178.                        GUI_SendKeyMsg(GUI_KEY_BACKSPACE, 1);
  179.                        break;
  180.                    case JOY_DOWN_L:            /* 摇杆LEFT键按下,实现光标左移 */
  181.                        GUI_SendKeyMsg(GUI_KEY_LEFT, 1);
  182.                        break;
  183.                    case JOY_DOWN_R:            /* 摇杆RIGHT键按下,实现光标右移 */
  184.                        GUI_SendKeyMsg(GUI_KEY_RIGHT, 1);
  185.                        break;
  186.                    case JOY_DOWN_OK:           /* 摇杆OK键按下,发送GUI_KEY_ENTER消息,会被聚焦的按钮或者
  187.                                                   WM_KEY消息所接受并处理,功能都是关闭对话框。*/
  188.                        GUI_SendKeyMsg(GUI_KEY_ENTER, 1);
  189.                        break;
  190.                    default:
  191.                        /* 其它的键值不处理 */
  192.                        break;
  193.               }
  194.                   
  195.          }
  196.         
  197.          OSTimeDly(20, OS_OPT_TIME_DLY, &err);
  198.      }
  199. }
  200. /*
  201. *********************************************************************************************************
  202. *    函 数 名: AppTaskCom
  203. *    功能说明: 暂未使用
  204. *    形    参: p_arg 是在创建该任务时传递的形参
  205. *    返 回 值: 无
  206.      优 先 级: 5
  207. *********************************************************************************************************
  208. */
  209. static void AppTaskCOM(void *p_arg)
  210. {
  211.      OS_ERR  err;      
  212.    
  213.      (void)p_arg;
  214.    
  215.      while(1)
  216.      {   
  217.          OSTimeDly(500, OS_OPT_TIME_DLY, &err);
  218.      }                                                                                                
  219. }
  220. /*
  221. *********************************************************************************************************
  222. *    函 数 名: AppTaskGUI
  223. *    功能说明: GUI任务,最低优先级                        
  224. *    形    参:p_arg 是在创建该任务时传递的形参
  225. *    返 回 值: 无
  226. *   优 先 级:OS_CFG_PRIO_MAX - 4u
  227. *********************************************************************************************************
  228. */
  229. static void AppTaskGUI(void *p_arg)
  230. {
  231.     (void)p_arg;       /* 避免编译器告警 */
  232.         
  233.      while (1)
  234.      {
  235.          MainTask();
  236.      }
  237. }
复制代码
emWin任务的具体实现(在MainTask.c文件里面):
  1. #include "MainTask.h"
  2. #include "includes.h"
  3. /*
  4. *********************************************************************************************************
  5. *                                         宏定义
  6. *********************************************************************************************************
  7. */
  8. #define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
  9. #define ID_LISTVIEW_0 (GUI_ID_USER + 0x01)
  10. /*
  11. *********************************************************************************************************
  12. *                           GUI_WIDGET_CREATE_INFO类型数组
  13. *********************************************************************************************************
  14. */
  15. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
  16. {
  17.      { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 800, 480, 0, 0x64, 0 },
  18.      { LISTVIEW_CreateIndirect, "Listview", ID_LISTVIEW_0, 30, 20, 350, 160, 0, 0x0, 0 },
  19. };
  20. /*
  21. *********************************************************************************************************
  22. *    函 数 名: _cbDialog
  23. *    功能说明: 对话框回调函数        
  24. *    形    参: pMsg  回调参数
  25. *    返 回 值: 无
  26. *********************************************************************************************************
  27. */
  28. static void _cbDialog(WM_MESSAGE * pMsg)
  29. {
  30.      WM_HWIN hItem;
  31.      int     NCode;
  32.      int     Id;
  33.      HEADER_Handle hHeader;
  34.      char    buf[10];
  35.      static char  Value = 0;
  36.      switch (pMsg->MsgId)
  37.      {
  38.          case WM_INIT_DIALOG:
  39.             
  40.               //
  41.               // 初始化框架窗口
  42.               //
  43.               hItem = pMsg->hWin;
  44.               FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
  45.               FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);
  46.               FRAMEWIN_SetText(hItem, "armfly");
  47.         
  48.               //
  49.               // 初始列表控件
  50.               //
  51.               hItem = WM_GetDialogItem(pMsg->hWin, ID_LISTVIEW_0);
  52.               /* 设置列表控件中header控件的所显示文本的字体 */
  53.               hHeader = LISTVIEW_GetHeader(hItem);
  54.               HEADER_SetFont(hHeader, GUI_FONT_16_ASCII);
  55.               /* 添加四列表,调用一次函数LISTVIEW_AddColumn添加一列 */
  56.               LISTVIEW_AddColumn(hItem, 80, "STM32-V3", GUI_TA_HCENTER | GUI_TA_VCENTER);
  57.               LISTVIEW_AddColumn(hItem, 80, "STM32-V4", GUI_TA_HCENTER | GUI_TA_VCENTER);
  58.               LISTVIEW_AddColumn(hItem, 80, "STM32-V5", GUI_TA_HCENTER | GUI_TA_VCENTER);
  59.               LISTVIEW_AddColumn(hItem, 80, "STM32-V6", GUI_TA_HCENTER | GUI_TA_VCENTER);
  60.             
  61.               /* 添加三行,调用一次函数LISTVIEW_AddRow添加一行 */
  62.               LISTVIEW_AddRow(hItem, NULL);
  63.               LISTVIEW_AddRow(hItem, NULL);
  64.               LISTVIEW_AddRow(hItem, NULL);
  65.         
  66.               /* 为列表控件三行四列共12个选项全部添加文本 */
  67.               LISTVIEW_SetItemText(hItem, 0, 0, "A00");
  68.               LISTVIEW_SetItemText(hItem, 1, 0, "A01");
  69.               LISTVIEW_SetItemText(hItem, 2, 0, "A02");
  70.               LISTVIEW_SetItemText(hItem, 3, 0, "A03");
  71.               LISTVIEW_SetItemText(hItem, 0, 1, "B10");
  72.               LISTVIEW_SetItemText(hItem, 1, 1, "B11");
  73.               LISTVIEW_SetItemText(hItem, 2, 1, "B12");
  74.               LISTVIEW_SetItemText(hItem, 3, 1, "B13");
  75.               LISTVIEW_SetItemText(hItem, 0, 2, "C20");
  76.               LISTVIEW_SetItemText(hItem, 1, 2, "C21");
  77.               LISTVIEW_SetItemText(hItem, 2, 2, "C22");
  78.               LISTVIEW_SetItemText(hItem, 3, 2, "C23");
  79.             
  80.               /* 设置列表控件选项中所显示文本的字体 */
  81.               LISTVIEW_SetFont(hItem, GUI_FONT_16_ASCII);
  82.               /* 设置列表控件表格可见 */
  83.               LISTVIEW_SetGridVis(hItem, 1);
  84.               break;
  85.         
  86.          case WM_NOTIFY_PARENT:
  87.               Id    = WM_GetId(pMsg->hWinSrc);
  88.               NCode = pMsg->Data.v;
  89.               switch(Id)
  90.               {
  91.                    case ID_LISTVIEW_0:
  92.                        switch(NCode)
  93.                        {
  94.                             case WM_NOTIFICATION_CLICKED:
  95.                                  break;
  96.                            
  97.                             case WM_NOTIFICATION_RELEASED:
  98.                                  break;
  99.                            
  100.                             case WM_NOTIFICATION_SEL_CHANGED:
  101.                                  break;
  102.                        }
  103.               }
  104.               break;
  105.             
  106.          case WM_TIMER:
  107.               /* 每100ms更新一次列表控件中第一个选项和最后一个选项所显示的文本,这里是做了一个简单的计数 */
  108.               hItem = WM_GetDialogItem(pMsg->hWin, ID_LISTVIEW_0);
  109.               sprintf(buf, "%d", Value++);
  110.               LISTVIEW_SetItemText(hItem, 0, 0, buf);
  111.               LISTVIEW_SetItemText(hItem, 3, 2, buf);
  112.             
  113.               WM_RestartTimer(pMsg->Data.v, 100);
  114.             
  115.          default:
  116.               WM_DefaultProc(pMsg);
  117.               break;
  118.      }
  119. }
  120. /*
  121. *********************************************************************************************************
  122. *    函 数 名: CreateFramewin
  123. *    功能说明: 创建对话框      
  124. *    形    参: 无
  125. *    返 回 值: 返回对话框句柄
  126. *********************************************************************************************************
  127. */
  128. WM_HWIN CreateFramewin(void)
  129. {
  130.      WM_HWIN hWin;
  131.      hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
  132.      return hWin;
  133. }
  134. /*
  135. *********************************************************************************************************
  136. *    函 数 名: MainTask
  137. *    功能说明: GUI主函数
  138. *    形    参: 无
  139. *    返 回 值: 无
  140. *********************************************************************************************************
  141. */
  142. void MainTask(void)
  143. {
  144.      WM_HWIN hDlg;
  145.    
  146.      /* 初始化 */
  147.      GUI_Init();
  148.    
  149.      /*
  150.       关于多缓冲和窗口内存设备的设置说明
  151.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  152.            WM_MULTIBUF_Enable(1);
  153.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  154.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  155.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  156.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  157.         4. 所有emWin例子默认是开启三缓冲。
  158.      */
  159.      WM_MULTIBUF_Enable(1);
  160.    
  161.      /*
  162.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  163.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  164.      */
  165.     //TOUCH_Calibration();
  166.    
  167.      /* 创建对话框 */
  168.      hDlg = CreateFramewin();
  169.    
  170.      /* 为对话框创建一个溢出时间是100ms的定时器 */
  171.      WM_CreateTimer(WM_GetClientWindow(hDlg), 0, 100, 0);
  172.         
  173.      while(1)
  174.      {
  175.          GUI_Delay(50);
  176.      }
  177. }
  178. /*
  179. *********************************************************************************************************
  180. *                                         宏定义
  181. *********************************************************************************************************
  182. */
  183. #define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
  184. #define ID_EDIT_0   (GUI_ID_USER + 0x01)
  185. #define ID_EDIT_1   (GUI_ID_USER + 0x03)
  186. /*
  187. *********************************************************************************************************
  188. *                           GUI_WIDGET_CREATE_INFO类型数组
  189. *********************************************************************************************************
  190. */
  191. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
  192. {
  193.      { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 320, 240, 0, 0x64, 0 },
  194.      { EDIT_CreateIndirect, "Edit", ID_EDIT_0, 88, 27, 159, 29, 0, 0x64, 0 },
  195.      { EDIT_CreateIndirect, "Edit", ID_EDIT_1, 87, 73, 159, 30, 0, 0x64, 0 },
  196.      { BUTTON_CreateIndirect, "Button", GUI_ID_OK, 26, 139, 97, 31, 0, 0x0, 0 },
  197.      { BUTTON_CreateIndirect, "Button", GUI_ID_CANCEL, 179, 139, 100, 31, 0, 0x0, 0 },
  198. };
  199. /*
  200. *********************************************************************************************************
  201. *    函 数 名: _cbDialog
  202. *    功能说明: 对话框的回调函数
  203. *    形    参: pMsg 消息指针
  204. *    返 回 值: 无
  205. *********************************************************************************************************
  206. */
  207. static void _cbDialog(WM_MESSAGE * pMsg)
  208. {
  209.      int     NCode;
  210.      int     Id;
  211.      WM_HWIN hDlg;
  212.      WM_HWIN hItem;
  213.      hDlg = pMsg->hWin;
  214.      switch (pMsg->MsgId)
  215.      {
  216.          case WM_INIT_DIALOG:
  217.         
  218.              //
  219.               // 初始化框架窗口
  220.               //
  221.               hItem = pMsg->hWin;
  222.               FRAMEWIN_SetFont(hItem, GUI_FONT_24_ASCII);
  223.               FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
  224.               FRAMEWIN_SetText(hItem, "armfly");
  225.         
  226.               //
  227.               // 初始化编辑框控件
  228.               //
  229.               hItem = WM_GetDialogItem(pMsg->hWin, ID_EDIT_0);
  230.               EDIT_SetText(hItem, "www.armfly.com");
  231.               EDIT_SetTextAlign(hItem, GUI_TA_LEFT | GUI_TA_VCENTER);
  232.               EDIT_SetFont(hItem, GUI_FONT_16_ASCII);
  233.               EDIT_SetSel(hItem, 0, -1);  /* 设置选中编辑框中所有文本 */
  234.             
  235.               //
  236.               // 初始化边框控件
  237.               //
  238.               hItem = WM_GetDialogItem(pMsg->hWin, ID_EDIT_1);
  239.               EDIT_SetText(hItem, "www.baidu.com");
  240.               EDIT_SetFont(hItem, GUI_FONT_16_ASCII);
  241.               EDIT_SetTextAlign(hItem, GUI_TA_LEFT | GUI_TA_VCENTER);
  242.               EDIT_SetSel(hItem, 0, -1);  /* 设置选中编辑框中所有文本 */
  243.             
  244.               //
  245.               // 初始化按钮控件
  246.               //
  247.               hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_OK);
  248.               BUTTON_SetText(hItem, "OK");
  249.               BUTTON_SetFont(hItem, GUI_FONT_16_ASCII);
  250.             
  251.               //
  252.               // 初始化按钮控件
  253.               //
  254.               hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_CANCEL);
  255.               BUTTON_SetText(hItem, "Cancel");
  256.               BUTTON_SetFont(hItem, GUI_FONT_16_ASCII);
  257.               break;
  258.             
  259.           case WM_KEY:
  260.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  261.             {
  262.                    case GUI_KEY_ESCAPE:
  263.                     GUI_EndDialog(hDlg, 1);
  264.                     break;
  265.                   
  266.                 case GUI_KEY_ENTER:
  267.                     GUI_EndDialog(hDlg, 0);
  268.                     break;
  269.             }
  270.             break;
  271.             
  272.          case WM_NOTIFY_PARENT:
  273.               Id    = WM_GetId(pMsg->hWinSrc);
  274.               NCode = pMsg->Data.v;
  275.               switch(Id)
  276.               {
  277.                    /* 点击OK按钮,关闭对话框 */
  278.                    case GUI_ID_OK:
  279.                        switch(NCode)
  280.                        {
  281.                             case WM_NOTIFICATION_CLICKED:
  282.                                  break;
  283.                            
  284.                             case WM_NOTIFICATION_RELEASED:
  285.                                  GUI_EndDialog(hDlg, 0);
  286.                                  break;
  287.                        }
  288.                        break;
  289.    
  290.                    /* 点击CANCEL按钮,关闭对话框 */                     
  291.                    case GUI_ID_CANCEL:
  292.                        switch(NCode)
  293.                        {
  294.                             case WM_NOTIFICATION_CLICKED:
  295.                                  break;
  296.                            
  297.                             case WM_NOTIFICATION_RELEASED:
  298.                                  GUI_EndDialog(hDlg, 1);
  299.                                  break;
  300.                        }
  301.                        break;               
  302.               }
  303.               break;
  304.          default:
  305.               WM_DefaultProc(pMsg);
  306.      }
  307. }
  308. /*
  309. *********************************************************************************************************
  310. *    函 数 名: _cbDesktop
  311. *    功能说明: 桌面窗口的回调函数
  312. *    形    参: pMsg 消息指针
  313. *    返 回 值: 无
  314. *********************************************************************************************************
  315. */
  316. static void _cbDesktop(WM_MESSAGE * pMsg)
  317. {
  318.      switch (pMsg->MsgId)
  319.      {
  320.          /* 重绘 */
  321.          case WM_PAINT:
  322.               GUI_SetBkColor(GUI_RED);
  323.               GUI_Clear();
  324.               GUI_SetFont(&GUI_Font24_ASCII);
  325.               GUI_DispStringHCenterAt("WIDGET_EditWinmode", 160, 5);
  326.               GUI_DispNextLine();
  327.               GUI_SetFont(GUI_DEFAULT_FONT);
  328.               GUI_DispNextLine();
  329.               break;
  330.         
  331.          default:
  332.               WM_DefaultProc(pMsg);
  333.      }
  334. }
  335. /*
  336. *********************************************************************************************************
  337. *    函 数 名: MainTask
  338. *    功能说明: GUI主函数
  339. *    形    参: 无
  340. *    返 回 值: 无
  341. *********************************************************************************************************
  342. */
  343. void MainTask(void)
  344. {
  345.    
  346.      /* 初始化 */
  347.      GUI_Init();
  348.    
  349.      /*
  350.       关于多缓冲和窗口内存设备的设置说明
  351.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  352.            WM_MULTIBUF_Enable(1);
  353.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  354.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  355.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  356.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  357.         4. 所有emWin例子默认是开启三缓冲。
  358.      */
  359.      WM_MULTIBUF_Enable(1);
  360.    
  361.      /*
  362.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  363.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  364.      */
  365.     //TOUCH_Calibration();
  366.    
  367.      WM_SetCallback(WM_HBKWIN, _cbDesktop);
  368.    
  369.      while(1)
  370.      {
  371.          /* 创建阻塞式对话框 */
  372.          GUI_ExecDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbDialog, 0, 0, 0);
  373.          GUI_Delay(500);
  374.      }
  375. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-31 16:42:44 | 显示全部楼层
62.6 实验例程说明(裸机)


配套例子:
        V6-600_STemWin实验_键盘输入,实体按键操作控件(裸机)
实验目的:
         1.     本实验主要学习实体按键操作控件的使用。
         2.     emWin功能的实现在MainTask.c文件里面。
实验内容:
        1.     针对本例子创建的界面,其余按键操作实现的功能如下,第2条到第7条。
        2.     K3按钮按下,实现控件聚焦的切换。
        3.     摇杆向上按,实现删除编辑框控件光标后的字符。
        4.     摇杆向下按,实现删除编辑框控件光标前的字符。
        5.     摇杆向左按,实现光标左移。
        6.     摇杆向右按,实现光标右移。
        7.     摇杆按下OK键,发送按键消息GUI_KEY_ENTER,如果当前聚焦到按钮控件上,发送此消息会关闭对话框。如果未聚焦到按钮控件上,发送消息GUI_KEY_ENTER会被对话框回调函数中WM_KEY消息所接受,同样也是实现关闭对话框功能。
STemWin界面显示效果:
        800*480分辨率界面效果。
2.10.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文件中配置:
2.11.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. #define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
  9. #define ID_EDIT_0   (GUI_ID_USER + 0x01)
  10. #define ID_EDIT_1   (GUI_ID_USER + 0x03)
  11. /*
  12. *********************************************************************************************************
  13. *                           GUI_WIDGET_CREATE_INFO类型数组
  14. *********************************************************************************************************
  15. */
  16. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
  17. {
  18.      { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 320, 240, 0, 0x64, 0 },
  19.      { EDIT_CreateIndirect, "Edit", ID_EDIT_0, 88, 27, 159, 29, 0, 0x64, 0 },
  20.      { EDIT_CreateIndirect, "Edit", ID_EDIT_1, 87, 73, 159, 30, 0, 0x64, 0 },
  21.      { BUTTON_CreateIndirect, "Button", GUI_ID_OK, 26, 139, 97, 31, 0, 0x0, 0 },
  22.      { BUTTON_CreateIndirect, "Button", GUI_ID_CANCEL, 179, 139, 100, 31, 0, 0x0, 0 },
  23. };
  24. /*
  25. *********************************************************************************************************
  26. *    函 数 名: _cbDialog
  27. *    功能说明: 对话框的回调函数
  28. *    形    参: pMsg 消息指针
  29. *    返 回 值: 无
  30. *********************************************************************************************************
  31. */
  32. static void _cbDialog(WM_MESSAGE * pMsg)
  33. {
  34.      int     NCode;
  35.      int     Id;
  36.      WM_HWIN hDlg;
  37.      WM_HWIN hItem;
  38.      hDlg = pMsg->hWin;
  39.      switch (pMsg->MsgId)
  40.      {
  41.          case WM_INIT_DIALOG:
  42.         
  43.              //
  44.               // 初始化框架窗口
  45.               //
  46.               hItem = pMsg->hWin;
  47.               FRAMEWIN_SetFont(hItem, GUI_FONT_24_ASCII);
  48.               FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
  49.               FRAMEWIN_SetText(hItem, "armfly");
  50.         
  51.               //
  52.               // 初始化编辑框控件
  53.               //
  54.               hItem = WM_GetDialogItem(pMsg->hWin, ID_EDIT_0);
  55.               EDIT_SetText(hItem, "www.armfly.com");
  56.               EDIT_SetTextAlign(hItem, GUI_TA_LEFT | GUI_TA_VCENTER);
  57.               EDIT_SetFont(hItem, GUI_FONT_16_ASCII);
  58.               EDIT_SetSel(hItem, 0, -1);  /* 设置选中编辑框中所有文本 */
  59.             
  60.               //
  61.               // 初始化边框控件
  62.               //
  63.               hItem = WM_GetDialogItem(pMsg->hWin, ID_EDIT_1);
  64.               EDIT_SetText(hItem, "www.baidu.com");
  65.               EDIT_SetFont(hItem, GUI_FONT_16_ASCII);
  66.               EDIT_SetTextAlign(hItem, GUI_TA_LEFT | GUI_TA_VCENTER);
  67.               EDIT_SetSel(hItem, 0, -1);  /* 设置选中编辑框中所有文本 */
  68.             
  69.               //
  70.               // 初始化按钮控件
  71.               //
  72.               hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_OK);
  73.               BUTTON_SetText(hItem, "OK");
  74.               BUTTON_SetFont(hItem, GUI_FONT_16_ASCII);
  75.             
  76.               //
  77.               // 初始化按钮控件
  78.               //
  79.               hItem = WM_GetDialogItem(pMsg->hWin, GUI_ID_CANCEL);
  80.               BUTTON_SetText(hItem, "Cancel");
  81.               BUTTON_SetFont(hItem, GUI_FONT_16_ASCII);
  82.               break;
  83.             
  84.           case WM_KEY:
  85.             switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
  86.             {
  87.                    case GUI_KEY_ESCAPE:
  88.                     GUI_EndDialog(hDlg, 1);
  89.                     break;
  90.                   
  91.                 case GUI_KEY_ENTER:
  92.                     GUI_EndDialog(hDlg, 0);
  93.                     break;
  94.             }
  95.             break;
  96.             
  97.          case WM_NOTIFY_PARENT:
  98.               Id    = WM_GetId(pMsg->hWinSrc);
  99.               NCode = pMsg->Data.v;
  100.               switch(Id)
  101.               {
  102.                    /* 点击OK按钮,关闭对话框 */
  103.                    case GUI_ID_OK:
  104.                        switch(NCode)
  105.                        {
  106.                             case WM_NOTIFICATION_CLICKED:
  107.                                  break;
  108.                            
  109.                             case WM_NOTIFICATION_RELEASED:
  110.                                  GUI_EndDialog(hDlg, 0);
  111.                                  break;
  112.                         }
  113.                        break;
  114.    
  115.                    /* 点击CANCEL按钮,关闭对话框 */                     
  116.                   case GUI_ID_CANCEL:
  117.                        switch(NCode)
  118.                        {
  119.                             case WM_NOTIFICATION_CLICKED:
  120.                                  break;
  121.                            
  122.                             case WM_NOTIFICATION_RELEASED:
  123.                                  GUI_EndDialog(hDlg, 1);
  124.                                  break;
  125.                        }
  126.                        break;               
  127.               }
  128.               break;
  129.          default:
  130.               WM_DefaultProc(pMsg);
  131.      }
  132. }
  133. /*
  134. *********************************************************************************************************
  135. *    函 数 名: _cbDesktop
  136. *    功能说明: 桌面窗口的回调函数
  137. *    形    参: pMsg 消息指针
  138. *    返 回 值: 无
  139. *********************************************************************************************************
  140. */
  141. static void _cbDesktop(WM_MESSAGE * pMsg)
  142. {
  143.      switch (pMsg->MsgId)
  144.      {
  145.          /* 重绘 */
  146.          case WM_PAINT:
  147.               GUI_SetBkColor(GUI_RED);
  148.               GUI_Clear();
  149.               GUI_SetFont(&GUI_Font24_ASCII);
  150.               GUI_DispStringHCenterAt("WIDGET_EditWinmode", 160, 5);
  151.               GUI_DispNextLine();
  152.               GUI_SetFont(GUI_DEFAULT_FONT);
  153.               GUI_DispNextLine();
  154.               break;
  155.         
  156.          default:
  157.               WM_DefaultProc(pMsg);
  158.      }
  159. }
  160. /*
  161. *********************************************************************************************************
  162. *    函 数 名: _cbTimer
  163. *    功能说明: 创建对话框      
  164. *    形    参: pTM 消息指针
  165. *    返 回 值: 无
  166. *********************************************************************************************************
  167. */
  168. void _cbTimer(GUI_TIMER_MESSAGE * pTM)
  169. {
  170.      uint8_t  ucKeyCode;
  171.    
  172.      switch (pTM->Context)
  173.      {
  174.          case 0x01:
  175.               ucKeyCode = bsp_GetKey();
  176.             
  177.               if(ucKeyCode != KEY_NONE)
  178.               {
  179.                    switch (ucKeyCode)
  180.                    {
  181.                      
  182.                        case KEY_DOWN_K3:           /* K3键按下,实现TAB按键的功能*/
  183.                             GUI_SendKeyMsg(GUI_KEY_TAB, 1);
  184.                             break;
  185.                        case JOY_DOWN_U:            /* 摇杆UP键按下,实现删除光标后的字符 */
  186.                             GUI_SendKeyMsg(GUI_KEY_DELETE, 1);
  187.                             break;
  188.                        case JOY_DOWN_D:            /* 摇杆DOWN键按下,实现删除光标前的字符 */
  189.                             GUI_SendKeyMsg(GUI_KEY_BACKSPACE, 1);
  190.                             break;
  191.                        case JOY_DOWN_L:            /* 摇杆LEFT键按下,实现光标左移 */
  192.                             GUI_SendKeyMsg(GUI_KEY_LEFT, 1);
  193.                             break;
  194.                        case JOY_DOWN_R:            /* 摇杆RIGHT键按下,实现光标右移 */
  195.                             GUI_SendKeyMsg(GUI_KEY_RIGHT, 1);
  196.                             break;
  197.                        case JOY_DOWN_OK:           /* 摇杆OK键按下,发送GUI_KEY_ENTER消息,会被聚焦的按钮
  198. 或者WM_KEY消息所接受并处理,功能都是关闭对话框。*/
  199.                             GUI_SendKeyMsg(GUI_KEY_ENTER, 1);
  200.                             break;
  201.                        default:
  202.                             /* 其它的键值不处理 */
  203.                             break;
  204.                    }
  205.                      
  206.               }
  207.             
  208.               /* 此函数一定要调用,设置重新启动,要不仅执行一次 */
  209.               GUI_TIMER_Restart(pTM->hTimer);
  210.               break;
  211.          default:
  212.               break;
  213.      }
  214. }
  215. /*
  216. *********************************************************************************************************
  217. *    函 数 名: MainTask
  218. *    功能说明: GUI主函数
  219. *    形    参: 无
  220. *    返 回 值: 无
  221. *********************************************************************************************************
  222. */
  223. void MainTask(void)
  224. {
  225.      GUI_TIMER_HANDLE hTimer;
  226.    
  227.      /* 初始化 */
  228.      GUI_Init();
  229.    
  230.      /*
  231.       关于多缓冲和窗口内存设备的设置说明
  232.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  233.            WM_MULTIBUF_Enable(1);
  234.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  235.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  236.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  237.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  238.         4. 所有emWin例子默认是开启三缓冲。
  239.      */
  240.      WM_MULTIBUF_Enable(1);
  241.    
  242.      /*
  243.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  244.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  245.      */
  246.     //TOUCH_Calibration();
  247.    
  248.      WM_SetCallback(WM_HBKWIN, _cbDesktop);
  249.    
  250.      /* 创建定时器 */
  251.      hTimer = GUI_TIMER_Create(_cbTimer, /* 回调函数 */
  252.                              1000,/* 绝对时间,设置系统上电后1s作为溢出时间 */
  253.                              0x01, /* 可以任务此参数是区分不同定时器的ID,方便多个定时使用同一个回调函数 */
  254.                              0);   /* 保留,暂时未用到 */
  255.                         
  256.      /* 设置定时器周期为20ms */
  257.      GUI_TIMER_SetPeriod(hTimer, 20);
  258.         
  259.      while(1)
  260.      {
  261.           /* 创建阻塞式对话框 */
  262.          GUI_ExecDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbDialog, 0, 0, 0);
  263.          GUI_Delay(500);
  264.      }
  265. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-31 16:43:08 | 显示全部楼层
62.7 总结


        本章节就为大家讲解这么多,掌握了本章节配套的例子后,务必要自行创建一个界面进行实战演练,只有这样才能真正掌握此功能,此功能在实际项目中用到的地方很多。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-12 13:52 , Processed in 0.193667 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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