硬汉嵌入式论坛

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

[emWin教程入门篇] 第47章       BUTTON-按钮控件自定义回调函数,实现

[复制链接]

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

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





第47章       BUTTON-按钮控件自定义回调函数,实现各种按钮效果


          本章节为大家讲解按钮控件自定义回调函数,通过其回调函数就可以实现各种按钮效果。这方面的问题也是经常有初学者问,所以专门做一期教程。
47.1 初学者重要提示
47.2 按钮控件自定义回调函数的实现方法
47.3 官方WIDGET_ButtonRound.c实例讲解
47.4 实验例程说明(RTOS)
47.5 实验例程说明(裸机)
47.6 总结
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-1 17:56:47 | 显示全部楼层
47.1  初学者重要提示



1、很多时候,我们希望设计出不同效果的按钮出来,比如做一个音乐播放器界面将快进,快退,暂停,开始等都通过按钮来实现,这个时候时候按钮的自定义回调函数就派上用场了。希望初学者掌握这个重要的知识点。不仅仅是按钮控件,后面要讲解到的其它控件都是可以设置自定义回调函数。


2、按钮控件的所有API函数在emWin手册中都有讲解,下图是中文版手册里面API函数位置:
47.1.png


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

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-1 17:58:36 | 显示全部楼层
47.2   按钮控件自定义回调函数的实现方法


        按钮控件的本质也是窗口,所以也是有回调函数的,只是被封装了,用户看不到,不像我们使用窗口或者框架窗口的时候还需要专门的设置回调函数。
        实现自定义回调函数的关键就是函数WM_SetCallback,通过这个函数就可以重定向按钮的回调函数,从而也就可以实现各种效果的按钮。下面我们通过一个实例给大家介绍如何实现按钮控件的自定义回调函数。完整代码在例子V6-563_STemWin实验_Button按钮控通过自定义回调函数实现各种按钮效果(模拟器)里面:
  1. #include "DIALOG.h"
  2. /*
  3. *********************************************************************************************************
  4. *                                         图片位图数据
  5. *********************************************************************************************************
  6. */
  7. static GUI_CONST_STORAGE unsigned long _acpic1[] = {
  8.   0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  9.         0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  10.         0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  11.         /* 后面的数据未列出 */
  12. };
  13. GUI_CONST_STORAGE GUI_BITMAP bmpic1 = {
  14.   64, // xSize
  15.   64, // ySize
  16.   256, // BytesPerLine
  17.   32, // BitsPerPixel
  18.   (unsigned char *)_acpic1,  // Pointer to picture data
  19.   NULL,  // Pointer to palette
  20.   GUI_DRAW_BMP8888
  21. }
  22. /*
  23. *********************************************************************************************************
  24. *                                         宏定义
  25. *********************************************************************************************************
  26. */
  27. #define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
  28. #define ID_BUTTON_0   (GUI_ID_USER + 0x01)
  29. #define ID_BUTTON_1   (GUI_ID_USER + 0x02)
  30. /*
  31. *********************************************************************************************************
  32. *                           GUI_WIDGET_CREATE_INFO类型数组
  33. *********************************************************************************************************
  34. */
  35. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
  36. {
  37.   { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 800, 480, 0, 0x64, 0 },
  38.   { BUTTON_CreateIndirect,   "",         ID_BUTTON_0, 30, 30, 64, 64, 0, 0x0, 0 },
  39.   { BUTTON_CreateIndirect,   "",         ID_BUTTON_1, 30, 120, 120, 40, 0, 0x0, 0 },
  40. };
  41. /*
  42. *********************************************************************************************************
  43. *    函 数 名: _cbButton
  44. *    功能说明: 按钮回调函数
  45. *    形    参: pMsg  消息指针
  46. *    返 回 值: 无
  47. *********************************************************************************************************
  48. */
  49. static void _cbButton(WM_MESSAGE * pMsg) //--------------(3)
  50. {
  51.      WM_HWIN  hWin;
  52.      hWin  = pMsg->hWin;
  53.      switch (pMsg->MsgId)
  54.      {
  55.          case WM_PAINT:
  56.               if (BUTTON_IsPressed(hWin))
  57.               {
  58.                    GUI_SetBkColor(GUI_WHITE);
  59.                    GUI_Clear();
  60.                    GUI_SetAlpha(0xb0);
  61.                    GUI_DrawBitmap(&bmpic1, 0,0);
  62.                    GUI_SetAlpha(0);      
  63.               }
  64.               else
  65.               {
  66.                    GUI_DrawBitmap(&bmpic1, 0, 0);      
  67.               }
  68.               break;
  69.             
  70.          default:
  71.               BUTTON_Callback(pMsg);
  72.      }
  73. }
  74. /*
  75. *********************************************************************************************************
  76. *    函 数 名: _cbButton1
  77. *    功能说明: 按钮回调函数
  78. *    形    参: pMsg  消息指针
  79. *    返 回 值: 无
  80. *********************************************************************************************************
  81. */
  82. static void _cbButton1(WM_MESSAGE * pMsg)  //--------------(6)
  83. {
  84.      WM_HWIN  hWin;
  85.      GUI_RECT Rect;
  86.      hWin  = pMsg->hWin;
  87.      switch (pMsg->MsgId)
  88.      {
  89.          case WM_PAINT:
  90.               WM_GetClientRect(&Rect);
  91.               if (BUTTON_IsPressed(hWin))
  92.               {
  93.                    GUI_SetColor(GUI_DARKGRAY);
  94.                    GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 5);
  95.                    GUI_SetBkColor(GUI_DARKGRAY);
  96.                    GUI_SetColor(GUI_WHITE);
  97.               }
  98.               else
  99.               {
  100.                    GUI_SetColor(GUI_LIGHTBLUE);
  101.                    GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 5);
  102.                    GUI_SetBkColor(GUI_LIGHTBLUE);
  103.                    GUI_SetColor(GUI_WHITE);  
  104.               }
  105.             
  106.               GUI_SetFont(&GUI_Font16_ASCII);
  107.               GUI_DispStringInRect("LED1", &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
  108.               break;
  109.             
  110.          default:
  111.               BUTTON_Callback(pMsg);
  112.      }
  113. }
  114. /*
  115. *********************************************************************************************************
  116. *    函 数 名: _cbDialog
  117. *    功能说明: 对话框回调函数        
  118. *    形    参: pMsg  回调参数
  119. *    返 回 值: 无
  120. *********************************************************************************************************
  121. */
  122. static void _cbDialog(WM_MESSAGE * pMsg)
  123. {
  124.      WM_HWIN hItem;
  125.      int     NCode;
  126.      int     Id;
  127.      switch (pMsg->MsgId)
  128.      {
  129.          case WM_INIT_DIALOG:
  130.               //
  131.               // 初始化框架窗口
  132.               //
  133.               hItem = pMsg->hWin;
  134.               FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);
  135.               FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
  136.               FRAMEWIN_SetText(hItem, "armfly");
  137.             
  138.               //
  139.               // 初始化按钮控件
  140.               //
  141.               hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
  142.               WM_SetHasTrans(hItem);             //--------------(1)
  143.               WM_SetCallback(hItem, _cbButton);  //--------------(2)
  144.               //
  145.               // 初始化按钮控件
  146.               //
  147.               hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
  148.               WM_SetHasTrans(hItem);             //--------------(4)
  149.               WM_SetCallback(hItem, _cbButton1); //--------------(5)
  150.               break;
  151.          case WM_NOTIFY_PARENT:
  152.               Id    = WM_GetId(pMsg->hWinSrc);
  153.               NCode = pMsg->Data.v;
  154.               switch(Id)
  155.               {
  156.                    case ID_BUTTON_0:
  157.                        switch(NCode)
  158.                        {
  159.                             case WM_NOTIFICATION_CLICKED:
  160.                                  break;
  161.                             case WM_NOTIFICATION_RELEASED:
  162.                                  break;
  163.                        }
  164.                        break;
  165.               }
  166.               break;
  167.          default:
  168.          WM_DefaultProc(pMsg);
  169.          break;
  170.      }
  171. }
  172. /*
  173. *********************************************************************************************************
  174. *    函 数 名: CreateFramewin
  175. *    功能说明: 创建对话框      
  176. *    形    参: 无
  177. *    返 回 值: 返回对话框句柄
  178. *********************************************************************************************************
  179. */
  180. WM_HWIN CreateFramewin(void) {
  181.   WM_HWIN hWin;
  182.   hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
  183.   return hWin;
  184. }
  185. /*
  186. *********************************************************************************************************
  187. *    函 数 名: MainTask
  188. *    功能说明: GUI主函数
  189. *    形    参: 无
  190. *    返 回 值: 无
  191. *********************************************************************************************************
  192. */
  193. void MainTask(void)
  194. {
  195.      /* 初始化 */
  196.      GUI_Init();
  197.      /* 窗口自动使用存储设备 */
  198.      WM_SetCreateFlags(WM_CF_MEMDEV);
  199.      /* 创建对话框,使用GUIBulder生成的对话框创建函数 */
  200.      CreateFramewin();
  201.      while(1)
  202.      {
  203.          GUI_Delay(10);
  204.      }
  205. }
复制代码
这个例子在对话框上创建了2个按钮控件,每个按钮都重新设置了回调函数,实现了两种不同的按钮效果,一个是图标按钮,另一个是扁平化效果的按钮。
1.     通过函数WM_SetHasTrans设置ID为ID_BUTTON_0的按钮控件的透明效果,调用了这个函数有什么用呢?通过这个函数就可以将按钮回调函数中WM_PAINT消息没有重绘到的区域显示为完全透明,比如我们在按钮控件回调函数的WM_PAINT消息里面绘制了一个填充的圆圈,那么按钮控件所在区域的圆圈以外部分就是完全透明的。
2.     通过函数WM_SetCallback重新设置ID为ID_BUTTON_0的按钮控件的回调函数。
3.     通过此回调函数就可以设置各种效果的按钮了,这里是将按钮设置成一个图标。这个回调函数只有两个消息,一个是WM_PAINT,一个是默认的default,也就是说除了WM_PAINT消息以外,其它所有消息还是使用按钮控件默认的回调处理机制BUTTON_Callback来实现。这个问题解释清楚了,剩下就是WM_PAINT消息里面实现的功能了,这个消息里面实现了按钮按下和未按下两种状态的显示效果,通过函数BUTTON_IsPressed来区分这两种状态,返回1就是按下了,返回0就是未按下。
  1. /*
  2. 按下状态,按下后,我们通过函数GUI_SetAlpha设置图片显示出来的透明效果,
  3. 这样就将按下和未按下两种状态区分开了。
  4. */
  5. if (BUTTON_IsPressed(hWin))
  6. {
  7. /*
  8. 先将按钮显示区清为白色,清为白色是因为按钮所在的对话框客户端窗口背景色是白色的
  9.        另一个作用是背景图片是要跟这个白色区域做alpha融合,所以要清成白色。
  10. */
  11.      GUI_SetBkColor(GUI_WHITE);
  12.      GUI_Clear();
  13.      /* 设置图片的透明程度是0xb0,设置为0xFF表示完全透明,0x00表示完全不透明 */
  14.      GUI_SetAlpha(0xb0);
  15.      GUI_DrawBitmap(&bmpic1, 0,0);
  16.      /* 显示完毕图片后设置为默认的完全不透明 */
  17.      GUI_SetAlpha(0);      
  18. }
  19. /* 未按下状态,显示一个图标 */
  20. else
  21. {
  22.      GUI_DrawBitmap(&bmpic1, 0, 0);      
  23. }
复制代码
        通过上面的代码就实现了按钮未按下时显示的是一个图标,按下时是一个有透明效果的图标。
4.     通过函数WM_SetHasTrans设置ID为ID_BUTTON_1的按钮控件的透明效果。
5.     通过函数WM_SetCallback重新设置ID为ID_BUTTON_1的按钮控件的回调函数。
6.     通过此回调函数就可以设置各种效果的按钮了,这里是将按钮设置成圆角矩形。这里我们重点看WM_PAINT消息,其它跟第3条讲解的是一样的。
  1. /* 获取按钮的显示区坐标,即左上角坐标和右下角坐标 */
  2. WM_GetClientRect(&Rect);
  3. /* 按下状态,*/
  4. if (BUTTON_IsPressed(hWin))
  5. {
  6.      /* 设置前景色用于绘制圆角矩形 */
  7.      GUI_SetColor(GUI_DARKGRAY);
  8.      /* 圆角矩形绘制函数 */
  9.      GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 5);
  10.     /* 设置背景色和前景色用于函数GUI_DispStringInRect 显示文本LED1使用 */
  11.      GUI_SetBkColor(GUI_DARKGRAY);
  12.      GUI_SetColor(GUI_WHITE);
  13. }
  14. /* 未按下状态  */
  15. else
  16. {
  17. /* 设置前景色用于绘制圆角矩形 */
  18.      GUI_SetColor(GUI_LIGHTBLUE);
  19.      /* 圆角矩形绘制函数 */
  20.      GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 5);
  21.      /* 设置背景色和前景色用于函数GUI_DispStringInRect 显示文本LED1使用 */
  22.      GUI_SetBkColor(GUI_LIGHTBLUE);
  23.      GUI_SetColor(GUI_WHITE);  
  24. }
  25. /* 设置文本显示字体 */
  26. GUI_SetFont(&GUI_Font16_ASCII);
  27. /* 将文本显示到按钮区域的垂直居中和水平居中 */
  28. GUI_DispStringInRect("LED1", &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
复制代码
通过上面的代码就实现了按钮未按下和按下时两种不同的按钮颜色。实际显示效果如下,分辨率800*480:
47.3.png


通过学习这个实例,建议大家尝试设置各种其它的按钮显示效果。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-1 18:00:10 | 显示全部楼层
47.3  官方WIDGET_ButtonRound.c实例讲解

        这个DEMO在模拟器中的位置:
47.4.png

主要功能介绍:
        这个例子演示了按钮自定义回调函数的实现,通过其回调函数实现了一个圆形的按钮,由于是官方做的例子,所以细节的处理上更专业些。学习这个例子前务必先学习前面47.2小节的讲解
程序代码如下:
  1. #include <stddef.h>
  2. #include <string.h>
  3. #include "WM.h"
  4. #include "FRAMEWIN.h"
  5. #include "BUTTON.h"
  6. /*********************************************************************
  7. *
  8. *       Defines
  9. *
  10. **********************************************************************
  11. */
  12. //
  13. // Recommended memory to run the sample with adequate performance
  14. //
  15. #define RECOMMENDED_MEMORY (1024L * 5)
  16. /*********************************************************************
  17. *
  18. *       Static data
  19. *
  20. **********************************************************************
  21. */
  22. static int _Color;
  23. static int _Font;
  24. static int _Pressed;
  25. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
  26.   { FRAMEWIN_CreateIndirect, "Round button sample", 0,      50,  60, 200, 120, FRAMEWIN_CF_MOVEABLE },
  27.   { BUTTON_CreateIndirect,   "Button",   GUI_ID_BUTTON0,   100,  10,  80,  80 },
  28.   { BUTTON_CreateIndirect,   "Callback", GUI_ID_BUTTON1,    10,  10,  60,  20 },
  29.   { BUTTON_CreateIndirect,   "Font",     GUI_ID_BUTTON2,    10,  30,  60,  20 },
  30.   { BUTTON_CreateIndirect,   "Color",    GUI_ID_BUTTON3,    10,  50,  60,  20 },
  31.   { BUTTON_CreateIndirect,   "Cancel",   GUI_ID_CANCEL,     10,  70,  60,  20 }
  32. };
  33. /*********************************************************************
  34. *
  35. *       Static functions
  36. *
  37. **********************************************************************
  38. */
  39. /*********************************************************************
  40. *
  41. *       _OnPaint
  42. *
  43. * Function description
  44. *   Paints the owner drawn button
  45. */
  46. static void _OnPaint(BUTTON_Handle hObj) { //--------------(1)
  47.   int Index;
  48.   char ac[50];
  49.   GUI_RECT Rect;
  50.   Index = (WIDGET_GetState(hObj) & BUTTON_STATE_PRESSED) ? 1 : 0; //--------------(2)
  51.   WM_GetClientRect(&Rect);
  52.   //
  53.   // Draw filled ellipse with button background color
  54.   //
  55.   GUI_SetColor(BUTTON_GetBkColor(hObj, Index));
  56.   GUI_FillEllipse(Rect.x1 / 2, Rect.y1 / 2, Rect.x1 / 2, Rect.y1 / 2);
  57.   //
  58.   // Draw black shape
  59.   //
  60.   GUI_SetColor(GUI_BLACK);
  61.   GUI_DrawEllipse(Rect.x1 / 2, Rect.y1 / 2, Rect.x1 / 2, Rect.y1 / 2);
  62.   //
  63.   // Draw button text with widget attributes
  64.   //
  65.   GUI_SetColor(BUTTON_GetTextColor(hObj, Index));
  66.   GUI_SetBkColor(BUTTON_GetBkColor(hObj, Index));
  67.   GUI_SetFont(BUTTON_GetFont(hObj));
  68.   BUTTON_GetText(hObj, ac, sizeof(ac));
  69.   if (_Pressed) {                              //--------------(3)
  70.     strcpy(ac + strlen(ac), "\\npressed");
  71.   }
  72.   GUI_DispStringInRect(ac, &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
  73. }
  74. /*********************************************************************
  75. *
  76. *       _cbButton
  77. *
  78. * Function description
  79. *  1. Calls the owner draw function if the WM_PAINT message has been send
  80. *  2. Calls the original callback for further messages
  81. *  3. After processing the messages the function evaluates the pressed-state
  82. *     if the WM_TOUCH message has been send
  83. */
  84. static void _cbButton(WM_MESSAGE * pMsg) {  //--------------(4)
  85.   switch (pMsg->MsgId) {
  86.     case WM_PAINT:                          //--------------(5)
  87.       _OnPaint(pMsg->hWin);
  88.       break;
  89.     default:                                //--------------(6)
  90.       BUTTON_Callback(pMsg); // The original callback
  91.       break;
  92.   }
  93.   if (pMsg->MsgId == WM_TOUCH) {           //--------------(7)
  94.     if (BUTTON_IsPressed(pMsg->hWin)) {
  95.       if (!_Pressed) {
  96.         _Pressed = 1;
  97.       }
  98.     } else {
  99.       _Pressed = 0;
  100.     }
  101.   }
  102. }
  103. /*********************************************************************
  104. *
  105. *       _cbDialog
  106. *
  107. * Function description
  108. *   Dialog callback routine
  109. */
  110. static void _cbDialog(WM_MESSAGE * pMsg) {
  111.   int           NCode;
  112.   int           Id;
  113.   WM_HWIN       hDlg;
  114.   BUTTON_Handle hButton;
  115.   hDlg = pMsg->hWin;
  116.   switch (pMsg->MsgId) {
  117.     case WM_PAINT:
  118.       WM_DefaultProc(pMsg); // Handle dialog items    //--------------(8)
  119.       //
  120.       // After drawing the dialog items add some user drawn items to the window
  121.       //
  122.       GUI_SetPenSize(10);
  123.       GUI_SetColor(GUI_GREEN);
  124.       GUI_DrawLine( 95,  5, 185, 95);
  125.       GUI_SetColor(GUI_RED);
  126.       GUI_DrawLine( 95, 95, 185,  5);
  127.       break;
  128.     case WM_INIT_DIALOG:
  129.       hButton = WM_GetDialogItem(hDlg, GUI_ID_BUTTON0);
  130.       WM_SetHasTrans(hButton);              // Set transparency flag for button   //--------------(9)
  131.       break;
  132.     case WM_KEY:
  133.       switch (((WM_KEY_INFO *)(pMsg->Data.p))->Key) {
  134.         case GUI_KEY_ESCAPE:
  135.           GUI_EndDialog(hDlg, 1);
  136.           break;
  137.         case GUI_KEY_ENTER:
  138.           GUI_EndDialog(hDlg, 0);
  139.           break;
  140.       }
  141.       break;
  142.     case WM_NOTIFY_PARENT:
  143.       Id    = WM_GetId(pMsg->hWinSrc);      // Id of widget
  144.       NCode = pMsg->Data.v;                 // Notification code
  145.       switch (NCode) {
  146.         case WM_NOTIFICATION_RELEASED:      // React only if released  //--------------(10)
  147.           hButton = WM_GetDialogItem(hDlg, GUI_ID_BUTTON0);
  148.           if (Id == GUI_ID_BUTTON1) {       // Toggle callback //--------------(11)
  149.             if (WM_GetCallback(hButton) == _cbButton) {
  150.               WM_SetCallback(hButton, BUTTON_Callback);
  151.             } else {
  152.               WM_SetCallback(hButton, _cbButton);
  153.             }
  154.             WM_InvalidateWindow(hButton);
  155.           }
  156.           if (Id == GUI_ID_BUTTON2) {       // Toggle font //--------------(12)
  157.             if (_Font) {
  158.               BUTTON_SetFont(hButton, &GUI_Font13_1);
  159.             } else {
  160.               BUTTON_SetFont(hButton, &GUI_Font8x16);
  161.             }
  162.             _Font ^= 1;
  163.           }
  164.           if (Id == GUI_ID_BUTTON3) {       // Toggle color //--------------(13)
  165.             if (_Color) {
  166.               BUTTON_SetBkColor(hButton, 0, 0xaaaaaa);
  167.               BUTTON_SetBkColor(hButton, 1, GUI_WHITE);
  168.               BUTTON_SetTextColor(hButton, 0, GUI_BLACK);
  169.               BUTTON_SetTextColor(hButton, 1, GUI_BLACK);
  170.             } else {
  171.               BUTTON_SetBkColor(hButton, 0, GUI_BLUE);
  172.               BUTTON_SetBkColor(hButton, 1, GUI_RED);
  173.               BUTTON_SetTextColor(hButton, 0, GUI_WHITE);
  174.               BUTTON_SetTextColor(hButton, 1, GUI_YELLOW);
  175.             }
  176.             _Color ^= 1;
  177.           }
  178.           if (Id == GUI_ID_OK) {            // OK Button //--------------(14)
  179.             GUI_EndDialog(hDlg, 0);
  180.           }
  181.           if (Id == GUI_ID_CANCEL) {        // Cancel Button //--------------(15)
  182.             GUI_EndDialog(hDlg, 1);
  183.           }
  184.           break;
  185.       }
  186.       break;
  187.     default:
  188.       WM_DefaultProc(pMsg);
  189.   }
  190. }
  191. /*********************************************************************
  192. *
  193. *       Public code
  194. *
  195. **********************************************************************
  196. */
  197. /*********************************************************************
  198. *
  199. *       MainTask
  200. */
  201. void MainTask(void) {
  202.   GUI_Init();
  203.   //
  204.   // Check if recommended memory for the sample is available
  205.   //
  206.   if (GUI_ALLOC_GetNumFreeBytes() < RECOMMENDED_MEMORY) {
  207.     GUI_ErrorOut("Not enough memory available.");
  208.     return;
  209.   }
  210.   //
  211.   // Use memory devices for all windows
  212.   //
  213.   #if GUI_SUPPORT_MEMDEV
  214.     WM_SetCreateFlags(WM_CF_MEMDEV);
  215.     WM_EnableMemdev(WM_HBKWIN);
  216.   #endif
  217.   WM_SetDesktopColor(GUI_GREEN);
  218.   while(1) {
  219.     _Font = _Color = 0;
  220.     GUI_ExecDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbDialog, 0, 0, 0);
  221.     GUI_Delay(1000);
  222.   }
  223. }
  224. /*************************** End of file ****************************/
复制代码
1.     按钮自定义回调函数中WM_PAINT消息的处理。
2.     通过函数(WIDGET_GetState(hObj) & BUTTON_STATE_PRESSED) ? 1: 0返回当前按钮是按下还是未按下,按下的话,返回数值1,未按下返回数值0。根据这个返回值,在WM_PIANT消息里面绘制按钮按下和未按下两种状态的显示效果。
3.     根据变量_Pressed的数值设置是否显示字符,如果变量数值非0表示按钮被按下,显示字符Button pressed,如果未按下,仅显示字符Button。变量_Pressed数值的改变是在按钮回调函数_cbButton里面修改的。其实这里直接使用第2条中函数(WIDGET_GetState(hObj) &BUTTON_STATE_PRESSED) ? 1 : 0的返回值就可以的,官方这里设计的稍有些啰嗦了。
4.     按钮自定义的回调函数。
5.     按钮自定义回调函数中WM_PAINT消息的处理。
6.     按钮回调函数中,除了WM_PIANT消息,其它消息的处理继续使用系统默认的函数BUTTON_Callback(pMsg)来实现。
7.     如果按钮被按下,回调函数首先收到的就是这个WM_TOUCH消息,然后才是WM_PAINT消息的处理,这样的话,就可以通过这个消息配合函数BUTTON_IsPressed(pMsg->hWin)来设置变量_Pressed,赋值为1表示按下,赋值为0表示未按下。
8.     函数WM_DefaultProc(pMsg)放在这里比较巧妙,先调用这个函数的话,系统就会按照默认配置先重绘对话框,然后用户在这个基础上再绘制自己需要的内容。
9.     通过函数WM_SetHasTrans设置ID为GUI_ID_BUTTON0的按钮控件的透明效果。
10.  按钮释放后的消息处理。
11.  按钮ID为GUI_ID_BUTTON1的按钮释放消息处理,这里实现对ID为GUI_ID_BUTTON0按钮的回调函数切换。
12.  按钮ID为GUI_ID_BUTTON2的按钮释放消息处理,这里实现对ID为GUI_ID_BUTTON0按钮显示字体的切换。
13.  按钮ID为GUI_ID_BUTTON3的按钮释放消息处理,这里实现对ID为GUI_ID_BUTTON0按钮显示文本的背景色和前景色的切换。
14.  按钮ID为GUI_ID_OK的按钮释放消息处理,此按钮在本程序未用到,因为没有创建ID为GUI_ID_OK的按钮。
15.  按钮ID为GUI_ID_CANCEL的按钮释放消息处理,这里实现关闭阻塞式对话框。如果关闭了,1秒后会重新创建这个对话框,如此循环。
显示效果如下:
47.5.png
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-1 18:05:10 | 显示全部楼层
47.4  实验例程说明(RTOS)


配套例子:
        V6-561_STemWin实验_Button按钮控通过自定义回调函数实现各种按钮效果(RTOS)
实验目的:
        1.     本实验主要学习通过按钮自定义回调函数实现各种按钮效果。这里实现了两种按钮效果,一个是图标按钮,另一个是扁平化效果的按钮。
        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任务。
μCOS-III任务调试信息(按K1按键,串口打印):
47.6.png

STemWin界面显示效果:
        800*480分辨率界面效果。
47.7.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. static GUI_CONST_STORAGE unsigned long _acpic1[] = {
  9.   0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  10.         0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  11.         0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  12.         /* 后面的数据未列出 */
  13. };
  14. GUI_CONST_STORAGE GUI_BITMAP bmpic1 = {
  15.   64, // xSize
  16.   64, // ySize
  17.   256, // BytesPerLine
  18.   32, // BitsPerPixel
  19.   (unsigned char *)_acpic1,  // Pointer to picture data
  20.   NULL,  // Pointer to palette
  21.   GUI_DRAW_BMP8888
  22. }
  23. /*
  24. *********************************************************************************************************
  25. *                                         宏定义
  26. *********************************************************************************************************
  27. */
  28. #define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
  29. #define ID_BUTTON_0   (GUI_ID_USER + 0x01)
  30. #define ID_BUTTON_1   (GUI_ID_USER + 0x02)
  31. /*
  32. *********************************************************************************************************
  33. *                           GUI_WIDGET_CREATE_INFO类型数组
  34. *********************************************************************************************************
  35. */
  36. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
  37. {
  38.   { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 800, 480, 0, 0x64, 0 },
  39.   { BUTTON_CreateIndirect,   "",         ID_BUTTON_0, 30, 30, 80, 80, 0, 0x0, 0 },
  40.   { BUTTON_CreateIndirect,   "",         ID_BUTTON_1, 30, 150, 120, 40, 0, 0x0, 0 },
  41. };
  42. /*
  43. *********************************************************************************************************
  44. *    函 数 名: _cbButton
  45. *    功能说明: 按钮回调函数
  46. *    形    参: pMsg  消息指针
  47. *    返 回 值: 无
  48. *********************************************************************************************************
  49. */
  50. static void _cbButton(WM_MESSAGE * pMsg)
  51. {
  52.      WM_HWIN  hWin;
  53.      hWin  = pMsg->hWin;
  54.      switch (pMsg->MsgId)
  55.      {
  56.          case WM_PAINT:
  57.               if (BUTTON_IsPressed(hWin))
  58.               {
  59.                    GUI_SetBkColor(GUI_WHITE);
  60.                    GUI_Clear();
  61.                    GUI_SetAlpha(0xb0);
  62.                    GUI_DrawBitmap(&bmpic1, 8, 8);
  63.                    GUI_SetAlpha(0);      
  64.               }
  65.               else
  66.               {
  67.                    GUI_DrawBitmap(&bmpic1, 8, 8);      
  68.               }
  69.               break;
  70.             
  71.          default:
  72.               BUTTON_Callback(pMsg);
  73.      }
  74. }
  75. /*
  76. *********************************************************************************************************
  77. *    函 数 名: _cbButton1
  78. *    功能说明: 按钮回调函数
  79. *    形    参: pMsg  消息指针
  80. *    返 回 值: 无
  81. *********************************************************************************************************
  82. */
  83. static void _cbButton1(WM_MESSAGE * pMsg)
  84. {
  85.      WM_HWIN  hWin;
  86.      GUI_RECT Rect;
  87.      hWin  = pMsg->hWin;
  88.      switch (pMsg->MsgId)
  89.      {
  90.          case WM_PAINT:
  91.               WM_GetClientRect(&Rect);
  92.               if (BUTTON_IsPressed(hWin))
  93.               {
  94.                    GUI_SetColor(GUI_DARKGRAY);
  95.                    GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 5);
  96.                    GUI_SetBkColor(GUI_DARKGRAY);
  97.                    GUI_SetColor(GUI_WHITE);
  98.               }
  99.               else
  100.               {
  101.                    GUI_SetColor(GUI_LIGHTBLUE);
  102.                    GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 5);
  103.                    GUI_SetBkColor(GUI_LIGHTBLUE);
  104.                    GUI_SetColor(GUI_WHITE);  
  105.               }
  106.             
  107.               GUI_SetFont(&GUI_Font16_ASCII);
  108.               GUI_DispStringInRect("LED1", &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
  109.               break;
  110.             
  111.          default:
  112.               BUTTON_Callback(pMsg);
  113.      }
  114. }
  115. /*
  116. *********************************************************************************************************
  117. *    函 数 名: _cbDialog
  118. *    功能说明: 对话框回调函数        
  119. *    形    参: pMsg  回调参数
  120. *    返 回 值: 无
  121. *********************************************************************************************************
  122. */
  123. static void _cbDialog(WM_MESSAGE * pMsg)
  124. {
  125.      WM_HWIN hItem;
  126.      int     NCode;
  127.      int     Id;
  128.      switch (pMsg->MsgId)
  129.      {
  130.          case WM_INIT_DIALOG:
  131.               //
  132.               // 初始化框架窗口
  133.               //
  134.               hItem = pMsg->hWin;
  135.               FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);
  136.               FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
  137.               FRAMEWIN_SetText(hItem, "armfly");
  138.             
  139.               //
  140.               // 初始化按钮控件
  141.               //
  142.               hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
  143.               WM_SetHasTrans(hItem);
  144.               WM_SetCallback(hItem, _cbButton);
  145.               //
  146.               // 初始化按钮控件
  147.               //
  148.               hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
  149.               WM_SetHasTrans(hItem);
  150.               WM_SetCallback(hItem, _cbButton1);
  151.               break;
  152.          case WM_NOTIFY_PARENT:
  153.               Id    = WM_GetId(pMsg->hWinSrc);
  154.               NCode = pMsg->Data.v;
  155.               switch(Id)
  156.               {
  157.                    case ID_BUTTON_0:
  158.                        switch(NCode)
  159.                        {
  160.                             case WM_NOTIFICATION_CLICKED:
  161.                                  break;
  162.                             case WM_NOTIFICATION_RELEASED:
  163.                                  break;
  164.                        }
  165.                        break;
  166.               }
  167.               break;
  168.          default:
  169.          WM_DefaultProc(pMsg);
  170.          break;
  171.      }
  172. }
  173. /*
  174. *********************************************************************************************************
  175. *    函 数 名: CreateFramewin
  176. *    功能说明: 创建对话框      
  177. *    形    参: 无
  178. *    返 回 值: 返回对话框句柄
  179. *********************************************************************************************************
  180. */
  181. WM_HWIN CreateFramewin(void)
  182. {
  183.      WM_HWIN hWin;
  184.      hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
  185.      return hWin;
  186. }
  187. /*
  188. *********************************************************************************************************
  189. *    函 数 名: MainTask
  190. *    功能说明: GUI主函数
  191. *    形    参: 无
  192. *    返 回 值: 无
  193. *********************************************************************************************************
  194. */
  195. void MainTask(void)
  196. {
  197.    
  198.      /* 初始化 */
  199.      GUI_Init();
  200.    
  201.      /*
  202.       关于多缓冲和窗口内存设备的设置说明
  203.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  204.            WM_MULTIBUF_Enable(1);
  205.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  206.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  207.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  208.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  209.         4. 所有emWin例子默认是开启三缓冲。
  210.      */
  211.      WM_MULTIBUF_Enable(1);
  212.    
  213.      /*
  214.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  215.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  216.      */
  217.     //TOUCH_Calibration();
  218.    
  219.      /* 创建对话框 */
  220.      CreateFramewin();
  221.    
  222.      while(1)
  223.      {
  224.          GUI_Delay(10);
  225.      }
  226. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-1 18:08:20 | 显示全部楼层
47.5    实验例程说明(裸机)


配套例子:
       V6-562_STemWin实验_Button按钮控通过自定义回调函数实现各种按钮效果(裸机)
实验目的:
        1.     本实验主要学习通过按钮自定义回调函数实现各种按钮效果。这里实现了两种按钮效果,一个是图标按钮,另一个是扁平化效果的按钮。
        2.     emWin功能的实现在MainTask.c文件里面。
STemWin界面显示效果:
        800*480分辨率界面效果。
47.8.png


STemWin动态内存配置:
        GUIConf.c文件中的配置如下:
  1. #define EX_SRAM   1/*1 used extern sram, 0 used internal sram */
  2. #if EX_SRAM
  3. #define GUI_NUMBYTES  (1024*1024*8)
  4. #else
  5. #define GUI_NUMBYTES  (100*1024)
  6. #endif
复制代码
        通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:
#define EX_SRAM    1 表示使用外部SDRAM作为emWin动态内存,大小8MB。
#define EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。
默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。
STemWin底层接口配置:
        LCDConf_Lin_Template.c文件中共12项emWin配置:
  1. /*
  2. **********************************************************************************************************
  3.                                           用户可以配置的选项
  4. **********************************************************************************************************
  5. */
  6. /* 0. 在官方代码的基础上再做优化,官方的部分函数效率低,耗内存, 0表示优化 */
  7. #define emWin_Optimize   0
  8. /*
  9.   1. 显示屏的物理分辨率,驱动已经做了显示屏自适应,支持4.3寸,5寸和7寸屏
  10.      这里填写自适应显示屏中的最大分辨率。
  11. */
  12. #define XSIZE_PHYS       800
  13. #define YSIZE_PHYS       480
  14. /* 2. 多缓冲 / 虚拟屏,多缓冲和虚拟屏不可同时使用,emWin不支持 */
  15. #define NUM_BUFFERS      3 /* 定义多缓冲个数,仅可以设置1,2和3,也就是最大支持三缓冲 */
  16. #define NUM_VSCREENS     1 /* 定义虚拟屏个数 */
  17. /* 3. 没有图层激活时,背景色设置, 暂时未用到 */
  18. #define BK_COLOR         GUI_DARKBLUE
  19. /*
  20.    4. 重定义图层数,对于STM32F429/439,用户可以选择一个图层或者两个图层,不支持三图层
  21.       (1). 设置GUI_NUM_LAYERS = 1时,即仅使用图层1时,默认触摸值是发送给图层1的。
  22.        (2). 设置GUI_NUM_LAYERS = 2时,即图层1和图层2都已经使能,此时图层2是顶层,
  23.             用户需要根据自己的使用情况设置如下两个地方。
  24.             a. 在bsp_touch.c文件中的函数TOUCH_InitHard里面设置参数State.Layer = 1,1就表示
  25.                给图层2发送触摸值。
  26.             b. 调用GUI_Init函数后,调用函数GUI_SelectLayer(1), 设置当前操作的是图层2。
  27. */
  28. #undef  GUI_NUM_LAYERS
  29. #define GUI_NUM_LAYERS    1
  30. /*
  31.    5. 设置图层1和图层2对应的显存地址
  32.       (1) EXT_SDRAM_ADDR 是SDRAM的首地址。
  33.       (2) LCD_LAYER0_FRAME_BUFFER 是图层1的显存地址。
  34.        (3) LCD_LAYER1_FRAME_BUFFER 是图层2的显存地址。
  35.        (4) 每个图层的显存大小比较考究,这里进行下简单的说明。
  36.            如果用户选择的颜色模式 = 32位色ARGB8888,显存的大小:
  37.            XSIZE_PHYS * YSIZE_PHYS * 4 * NUM_VSCREENS * NUM_BUFFERS
  38.          
  39.            颜色模式 = 24位色RGB888,显存的大小:
  40.            XSIZE_PHYS * YSIZE_PHYS * 3 * NUM_VSCREENS * NUM_BUFFERS
  41.          
  42.            颜色模式 = 16位色RGB566,ARGB1555, ARGB4444,AL88,那么显存的大小就是:
  43.            XSIZE_PHYS * YSIZE_PHYS * 2 * NUM_VSCREENS * NUM_BUFFERS
  44.            颜色模式 = 8位色L8,AL44,那么显存的大小就是:
  45.            XSIZE_PHYS * YSIZE_PHYS * 1 * NUM_VSCREENS * NUM_BUFFERS  
  46.      
  47.       这里为了方便起见,将开发板配套的16MB的SDRAM前8MB分配给LCD显存使用,后8MB用于emWin动态内存。
  48.        对于24位色,16位色,8位色,用户可以对其使能三缓冲,并且使能双图层。但是32位色也使能三缓冲和双
  49.        图层的话会超出8MB,所以用户根据自己的情况做显存和emWin动态内存的分配调整。
  50.          举一个例子,对于800*480分辨率的显示屏,使能32位色,三缓冲,那么最终一个图层需要的大小就是
  51.       800 * 480 * 4 * 3  = 4.394MB的空间,如果是双图层,已经超出8MB的分配范围。
  52.      
  53.       (5)为了方便起见,图层2的宏定义LCD_LAYER1_FRAME_BUFFER中的参数4是按照32位色设置的,如果用户的图层1
  54.          使用的是8位色,这里填数字1,如果是16位色,这里填2,如果是24位色,这里填3。
  55. */
  56. #define LCD_LAYER0_FRAME_BUFFER  EXT_SDRAM_ADDR
  57. #define LCD_LAYER1_FRAME_BUFFER  (LCD_LAYER0_FRAME_BUFFER + XSIZE_PHYS * YSIZE_PHYS * 4 * NUM_VSCREENS *
  58. NUM_BUFFERS)
  59. /*
  60.    6. STM32F429/439支持的颜色模式,所有模式都支持,用户可任意配置。
  61.       特别注意如下两个问题:
  62.        (1) 如果用户选择了ARGB8888或者RGB888模式,LCD闪烁比较厉害的话,
  63.            请降低LTDC的时钟大小,在文件bsp_tft_429.c的函数LCD_ConfigLTDC里面设置。
  64.            a. 一般800*480分辨率的显示屏,ARGB8888或者RGB888模式LTDC时钟选择10-20MHz即可。
  65.            b. 480*272分辨率的可以高些,取20MHz左右即可。
  66.        (2) 16位色或者8位色模式,LTDC的时钟频率一般可以比24位色或者32位色的高一倍。
  67. */
  68. #define _CM_ARGB8888      1
  69. #define _CM_RGB888        2
  70. #define _CM_RGB565        3
  71. #define _CM_ARGB1555      4
  72. #define _CM_ARGB4444      5
  73. #define _CM_L8            6
  74. #define _CM_AL44          7
  75. #define _CM_AL88          8
  76. /* 7. 配置图层1的颜色模式和分辨率大小 */
  77. #define COLOR_MODE_0      _CM_RGB565
  78. #define XSIZE_0           XSIZE_PHYS
  79. #define YSIZE_0           YSIZE_PHYS
  80. /* 8. 配置图层2的的颜色模式和分辨率大小 */
  81. #define COLOR_MODE_1      _CM_RGB565
  82. #define XSIZE_1           XSIZE_PHYS
  83. #define YSIZE_1           YSIZE_PHYS
  84. /* 9. 单图层情况下,根据用户选择的颜色模式可自动选择图层1的emWin的驱动和颜色模式 */
  85. #if   (COLOR_MODE_0 == _CM_ARGB8888)
  86.   #define COLOR_CONVERSION_0 GUICC_M8888I
  87.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_32
  88. #elif (COLOR_MODE_0 == _CM_RGB888)
  89.   #define COLOR_CONVERSION_0 GUICC_M888
  90.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_24
  91. #elif (COLOR_MODE_0 == _CM_RGB565)
  92.   #define COLOR_CONVERSION_0 GUICC_M565
  93.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  94. #elif (COLOR_MODE_0 == _CM_ARGB1555)
  95.   #define COLOR_CONVERSION_0 GUICC_M1555I
  96.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  97. #elif (COLOR_MODE_0 == _CM_ARGB4444)
  98.   #define COLOR_CONVERSION_0 GUICC_M4444I
  99.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  100. #elif (COLOR_MODE_0 == _CM_L8)
  101.   #define COLOR_CONVERSION_0 GUICC_8666
  102.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_8
  103. #elif (COLOR_MODE_0 == _CM_AL44)
  104.   #define COLOR_CONVERSION_0 GUICC_1616I
  105.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_8
  106. #elif (COLOR_MODE_0 == _CM_AL88)
  107.   #define COLOR_CONVERSION_0 GUICC_88666I
  108.   #define DISPLAY_DRIVER_0   GUIDRV_LIN_16
  109. #else
  110.   #error Illegal color mode 0!
  111. #endif
  112. /* 10. 双图层情况下,根据用户选择的颜色模式可自动选择图层2的emWin的驱动和颜色模式 */
  113. #if (GUI_NUM_LAYERS > 1)
  114. #if   (COLOR_MODE_1 == _CM_ARGB8888)
  115.   #define COLOR_CONVERSION_1 GUICC_M8888I
  116.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_32
  117. #elif (COLOR_MODE_1 == _CM_RGB888)
  118.   #define COLOR_CONVERSION_1 GUICC_M888
  119.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_24
  120. #elif (COLOR_MODE_1 == _CM_RGB565)
  121.   #define COLOR_CONVERSION_1 GUICC_M565
  122.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  123. #elif (COLOR_MODE_1 == _CM_ARGB1555)
  124.   #define COLOR_CONVERSION_1 GUICC_M1555I
  125.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  126. #elif (COLOR_MODE_1 == _CM_ARGB4444)
  127.   #define COLOR_CONVERSION_1 GUICC_M4444I
  128.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  129. #elif (COLOR_MODE_1 == _CM_L8)
  130.   #define COLOR_CONVERSION_1 GUICC_8666
  131.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_8
  132. #elif (COLOR_MODE_1 == _CM_AL44)
  133.   #define COLOR_CONVERSION_1 GUICC_1616I
  134.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_8
  135. #elif (COLOR_MODE_1 == _CM_AL88)
  136.   #define COLOR_CONVERSION_1 GUICC_88666I
  137.   #define DISPLAY_DRIVER_1   GUIDRV_LIN_16
  138. #else
  139.   #error Illegal color mode 1!
  140. #endif
  141. #else
  142. #undef XSIZE_0
  143. #undef YSIZE_0
  144. #define XSIZE_0       XSIZE_PHYS
  145. #define YSIZE_0       YSIZE_PHYS
  146. #endif
  147. /*11. 配置选项检测,防止配置错误或者某些选项没有配置 */
  148. #ifndef   XSIZE_PHYS
  149.   #error Physical X size of display is not defined!
  150. #endif
  151. #ifndef   YSIZE_PHYS
  152.   #error Physical Y size of display is not defined!
  153. #endif
  154. #ifndef   NUM_VSCREENS
  155.   #define NUM_VSCREENS 1
  156. #else
  157.   #if (NUM_VSCREENS <= 0)
  158.     #error At least one screeen needs to be defined!
  159.   #endif
  160. #endif
  161. #if (NUM_VSCREENS > 1) && (NUM_BUFFERS > 1)
  162.   #error Virtual screens and multiple buffers are not allowed!
  163. #endif
复制代码
        对于这12个配置选项,注释说明已经比较详细。默认情况下,本教程配套的emWin例子都是用的三缓冲,RGB565格式,且仅使用单图层。
程序设计:
栈大小分配:
        系统栈大小在startup_stm32f429_439xx.s文件中配置:
47.9.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. static GUI_CONST_STORAGE unsigned long _acpic1[] = {
  9.   0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  10.         0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  11.         0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000,
  12.         /* 后面的数据未列出 */
  13. };
  14. GUI_CONST_STORAGE GUI_BITMAP bmpic1 = {
  15.   64, // xSize
  16.   64, // ySize
  17.   256, // BytesPerLine
  18.   32, // BitsPerPixel
  19.   (unsigned char *)_acpic1,  // Pointer to picture data
  20.   NULL,  // Pointer to palette
  21.   GUI_DRAW_BMP8888
  22. }
  23. /*
  24. *********************************************************************************************************
  25. *                                         宏定义
  26. *********************************************************************************************************
  27. */
  28. #define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)
  29. #define ID_BUTTON_0   (GUI_ID_USER + 0x01)
  30. #define ID_BUTTON_1   (GUI_ID_USER + 0x02)
  31. /*
  32. *********************************************************************************************************
  33. *                           GUI_WIDGET_CREATE_INFO类型数组
  34. *********************************************************************************************************
  35. */
  36. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] =
  37. {
  38.   { FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 800, 480, 0, 0x64, 0 },
  39.   { BUTTON_CreateIndirect,   "",         ID_BUTTON_0, 30, 30, 80, 80, 0, 0x0, 0 },
  40.   { BUTTON_CreateIndirect,   "",         ID_BUTTON_1, 30, 150, 120, 40, 0, 0x0, 0 },
  41. };
  42. /*
  43. *********************************************************************************************************
  44. *    函 数 名: _cbButton
  45. *    功能说明: 按钮回调函数
  46. *    形    参: pMsg  消息指针
  47. *    返 回 值: 无
  48. *********************************************************************************************************
  49. */
  50. static void _cbButton(WM_MESSAGE * pMsg)
  51. {
  52.      WM_HWIN  hWin;
  53.      hWin  = pMsg->hWin;
  54.      switch (pMsg->MsgId)
  55.      {
  56.          case WM_PAINT:
  57.               if (BUTTON_IsPressed(hWin))
  58.               {
  59.                    GUI_SetBkColor(GUI_WHITE);
  60.                    GUI_Clear();
  61.                    GUI_SetAlpha(0xb0);
  62.                    GUI_DrawBitmap(&bmpic1, 8, 8);
  63.                    GUI_SetAlpha(0);      
  64.               }
  65.               else
  66.               {
  67.                    GUI_DrawBitmap(&bmpic1, 8, 8);      
  68.               }
  69.               break;
  70.             
  71.          default:
  72.               BUTTON_Callback(pMsg);
  73.      }
  74. }
  75. /*
  76. *********************************************************************************************************
  77. *    函 数 名: _cbButton1
  78. *    功能说明: 按钮回调函数
  79. *    形    参: pMsg  消息指针
  80. *    返 回 值: 无
  81. *********************************************************************************************************
  82. */
  83. static void _cbButton1(WM_MESSAGE * pMsg)
  84. {
  85.      WM_HWIN  hWin;
  86.      GUI_RECT Rect;
  87.      hWin  = pMsg->hWin;
  88.      switch (pMsg->MsgId)
  89.      {
  90.          case WM_PAINT:
  91.               WM_GetClientRect(&Rect);
  92.               if (BUTTON_IsPressed(hWin))
  93.               {
  94.                    GUI_SetColor(GUI_DARKGRAY);
  95.                    GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 5);
  96.                    GUI_SetBkColor(GUI_DARKGRAY);
  97.                    GUI_SetColor(GUI_WHITE);
  98.               }
  99.               else
  100.               {
  101.                    GUI_SetColor(GUI_LIGHTBLUE);
  102.                    GUI_FillRoundedRect(Rect.x0, Rect.y0, Rect.x1, Rect.y1, 5);
  103.                    GUI_SetBkColor(GUI_LIGHTBLUE);
  104.                    GUI_SetColor(GUI_WHITE);  
  105.               }
  106.             
  107.               GUI_SetFont(&GUI_Font16_ASCII);
  108.               GUI_DispStringInRect("LED1", &Rect, GUI_TA_HCENTER | GUI_TA_VCENTER);
  109.               break;
  110.             
  111.          default:
  112.               BUTTON_Callback(pMsg);
  113.      }
  114. }
  115. /*
  116. *********************************************************************************************************
  117. *    函 数 名: _cbDialog
  118. *    功能说明: 对话框回调函数        
  119. *    形    参: pMsg  回调参数
  120. *    返 回 值: 无
  121. *********************************************************************************************************
  122. */
  123. static void _cbDialog(WM_MESSAGE * pMsg)
  124. {
  125.      WM_HWIN hItem;
  126.      int     NCode;
  127.      int     Id;
  128.      switch (pMsg->MsgId)
  129.      {
  130.          case WM_INIT_DIALOG:
  131.               //
  132.               // 初始化框架窗口
  133.               //
  134.               hItem = pMsg->hWin;
  135.               FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);
  136.               FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);
  137.               FRAMEWIN_SetText(hItem, "armfly");
  138.             
  139.               //
  140.               // 初始化按钮控件
  141.               //
  142.               hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
  143.               WM_SetHasTrans(hItem);
  144.               WM_SetCallback(hItem, _cbButton);
  145.               //
  146.               // 初始化按钮控件
  147.               //
  148.               hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
  149.               WM_SetHasTrans(hItem);
  150.               WM_SetCallback(hItem, _cbButton1);
  151.               break;
  152.          case WM_NOTIFY_PARENT:
  153.               Id    = WM_GetId(pMsg->hWinSrc);
  154.               NCode = pMsg->Data.v;
  155.               switch(Id)
  156.               {
  157.                    case ID_BUTTON_0:
  158.                        switch(NCode)
  159.                        {
  160.                             case WM_NOTIFICATION_CLICKED:
  161.                                  break;
  162.                             case WM_NOTIFICATION_RELEASED:
  163.                                  break;
  164.                        }
  165.                        break;
  166.               }
  167.               break;
  168.          default:
  169.          WM_DefaultProc(pMsg);
  170.          break;
  171.      }
  172. }
  173. /*
  174. *********************************************************************************************************
  175. *    函 数 名: CreateFramewin
  176. *    功能说明: 创建对话框      
  177. *    形    参: 无
  178. *    返 回 值: 返回对话框句柄
  179. *********************************************************************************************************
  180. */
  181. WM_HWIN CreateFramewin(void)
  182. {
  183.      WM_HWIN hWin;
  184.      hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
  185.      return hWin;
  186. }
  187. /*
  188. *********************************************************************************************************
  189. *    函 数 名: MainTask
  190. *    功能说明: GUI主函数
  191. *    形    参: 无
  192. *    返 回 值: 无
  193. *********************************************************************************************************
  194. */
  195. void MainTask(void)
  196. {
  197.    
  198.      /* 初始化 */
  199.      GUI_Init();
  200.    
  201.      /*
  202.       关于多缓冲和窗口内存设备的设置说明
  203.         1. 使能多缓冲是调用的如下函数,用户要在LCDConf_Lin_Template.c文件中配置了多缓冲,调用此函数才有效:
  204.            WM_MULTIBUF_Enable(1);
  205.         2. 窗口使能使用内存设备是调用函数:WM_SetCreateFlags(WM_CF_MEMDEV);
  206.         3. 如果emWin的配置多缓冲和窗口内存设备都支持,二选一即可,且务必优先选择使用多缓冲,实际使用
  207.            STM32F429BIT6 + 32位SDRAM + RGB565/RGB888平台测试,多缓冲可以有效的降低窗口移动或者滑动时的撕裂
  208.            感,并有效的提高流畅性,通过使能窗口使用内存设备是做不到的。
  209.         4. 所有emWin例子默认是开启三缓冲。
  210.      */
  211.      WM_MULTIBUF_Enable(1);
  212.    
  213.      /*
  214.        触摸校准函数默认是注释掉的,电阻屏需要校准,电容屏无需校准。如果用户需要校准电阻屏的话,执行
  215.         此函数即可,会将触摸校准参数保存到EEPROM里面,以后系统上电会自动从EEPROM里面加载。
  216.      */
  217.     //TOUCH_Calibration();
  218.    
  219.      /* 创建对话框 */
  220.      CreateFramewin();
  221.    
  222.      while(1)
  223.      {
  224.          GUI_Delay(10);
  225.      }
  226. }
复制代码
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

740

主题

1326

回帖

3546

积分

管理员

春暖花开

Rank: 9Rank: 9Rank: 9

积分
3546
QQ
 楼主| 发表于 2017-3-1 18:08:46 | 显示全部楼层
47.6  总结

        本章节主要为大家讲解了按钮控件自定义回调函数的实现方法,对于这种方法,望初学者一定要掌握,后面章节学习其它控件做自定义回调函数,方法是相同的。
努力打造安富莱高质量微信公众号:点击扫描图片关注
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-16 18:18 , Processed in 0.254431 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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