emWin专题——emWin简介及模拟器的使用「建议收藏」

一、emWin简介1、emWin和ucGUI的关系

记得刚上大学的时候接触到单片机领域的一个图形界面叫ucGUI,也是跑在STM32上的,后来过了没多久网上查资料发现大家都是用的emWIn了,了解了一下它们之间的关系,其实是同一个东西。emWIn是在ucGUI的基础上发展起来的,两者同属一家公司(SEEGER)开发,没错就是咱买的JLINK调试器的那家公司,以前旧版本的ucGUI是开源的,后来emWin发展到5.0版本后进行了很大的更新,特别是底层驱动方面。但是emWIn5.xx版本向下完全的兼容低版本,也包括ucGUI5.xx以下的版本。emWIn5.xx以后的版本只有库没有源码,所以想要了解底层实现的话可以看早起的版本。

2、emWIn和STemWIn的关系

SEEGER公司授权给ST、NXP、Energy Micro等公司的处理器可以免费使用emWin。跑在ST处理器上的emWin我们称之为STemWin,STemWIn对ST的控制器做了专门的优化。出于一定的保护措施,STemWin的库是不能在其他芯片厂商的处理器上跑的,因为在STemWin初始化前要使能CRC校验。如果没有使能,STemWIn则启动不起来,KEIL MDK安装目录也带有emWIn的软件包,需要注册RL-ARM才可以使用。

二、模拟器的使用1、emWin模拟器

按照正常的思路,我们应该是在KEIL上写好了代码,然后再对工程进行编译,将程序下载到开发板上查看现象,但是对于嵌入式来说这样的调试方式还是太慢了,如果能在PC上直接仿真运行就可以省去下载代码和开发板上调试的时间了,而且仿真的编译速度也比KEIL更加的快。

目前emWIn已经更新到V6.10版本了,大家可以在官网(SEEGER官网)下载到不同版本的emWIn模拟器以及相关的手册资料,下载之前需要注册一个账号,因为外网原因下载速度可能比较慢。本文最后的资料链接里也附有这个文件。下面我用的是V5.32版本的来展示。目录结构如下:

我电脑上装的是VS2013直接双击sln文件就可以打开工程了,如果提示升级什么组件的话直接点确定。

然后直接点调试运行就可以看到运行的官方demo了。

2、emWin + uCosIII模拟器

这是我在网上找到的资料,看到有人把uCosIII和emWin模拟器移植到了一起,个人感觉挺好的,因为我们有时候可能把嵌入式操作系统和图形界面一起用上,而且emWin也是支持操作系统的。这个资源会在本文最后面给出。VS编译的时候可能会报错:错误 206 error LNK1281: 无法生成 SAFESEH 映像。 解决方法是:选中项目,右键菜单->属性->链接器->命令行,在“附加选项”框中 输入 /SAFESEH:NO ,然后点击应用。

三、GUIBuilder的使用有了PC端的模拟器其实还不够方便,因为这只是在运行阶段给我们提供了方便,而在代码的编写阶段能不能够一样给我们提供方便呢?就像QT、C#等等界面开发软件一样,支持用户拖拽控件生成代码的功能。GUIBuilder就是要完成这个功能。这个工具在KEIL的安装目录下就有,具体路径见下图。

双击GUIBuilder.exe看到编辑界面。

随便拖几个控件上去练练手:

完成后选择左上角的File->Save可以看到在当前目录下生成了一个.c文件FramewinDLG.c:

里面的代码如下:

代码语言:javascript代码运行次数:0运行复制/*********************************************************************

* *

* SEGGER Microcontroller GmbH & Co. KG *

* Solutions for real time microcontroller applications *

* *

**********************************************************************

* *

* C-file generated by: *

* *

* GUI_Builder for emWin version 5.24 *

* Compiled Jan 27 2014, 11:28:24 *

* (c) 2013 Segger Microcontroller GmbH & Co. KG *

* *

**********************************************************************

* *

* Internet: www.segger.com Support: support@segger.com *

* *

**********************************************************************

*/

// USER START (Optionally insert additional includes)

// USER END

#include "DIALOG.h"

/*********************************************************************

*

* Defines

*

**********************************************************************

*/

#define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)

#define ID_BUTTON_0 (GUI_ID_USER + 0x02)

#define ID_CHECKBOX_0 (GUI_ID_USER + 0x03)

#define ID_DROPDOWN_0 (GUI_ID_USER + 0x04)

// USER START (Optionally insert additional defines)

// USER END

/*********************************************************************

*

* Static data

*

**********************************************************************

*/

// USER START (Optionally insert additional static data)

// USER END

/*********************************************************************

*

* _aDialogCreate

*/

static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {

{ FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 320, 240, 0, 0x64, 0 },

{ BUTTON_CreateIndirect, "Button", ID_BUTTON_0, 96, 24, 80, 20, 0, 0x0, 0 },

{ CHECKBOX_CreateIndirect, "Checkbox", ID_CHECKBOX_0, 97, 53, 80, 20, 0, 0x0, 0 },

{ DROPDOWN_CreateIndirect, "Dropdown", ID_DROPDOWN_0, 104, 90, 80, 19, 0, 0x0, 0 },

// USER START (Optionally insert additional widgets)

// USER END

};

/*********************************************************************

*

* Static code

*

**********************************************************************

*/

// USER START (Optionally insert additional static code)

// USER END

/*********************************************************************

*

* _cbDialog

*/

static void _cbDialog(WM_MESSAGE * pMsg) {

WM_HWIN hItem;

int NCode;

int Id;

// USER START (Optionally insert additional variables)

// USER END

switch (pMsg->MsgId) {

case WM_INIT_DIALOG:

//

// Initialization of 'Framewin'

//

hItem = pMsg->hWin;

FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);

FRAMEWIN_SetText(hItem, "HelloWorld");

FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);

//

// Initialization of 'Checkbox'

//

hItem = WM_GetDialogItem(pMsg->hWin, ID_CHECKBOX_0);

CHECKBOX_SetText(hItem, "Check");

// USER START (Optionally insert additional code for further widget initialization)

// USER END

break;

case WM_NOTIFY_PARENT:

Id = WM_GetId(pMsg->hWinSrc);

NCode = pMsg->Data.v;

switch(Id) {

case ID_BUTTON_0: // Notifications sent by 'Button'

switch(NCode) {

case WM_NOTIFICATION_CLICKED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_RELEASED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

// USER START (Optionally insert additional code for further notification handling)

// USER END

}

break;

case ID_CHECKBOX_0: // Notifications sent by 'Checkbox'

switch(NCode) {

case WM_NOTIFICATION_CLICKED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_RELEASED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_VALUE_CHANGED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

// USER START (Optionally insert additional code for further notification handling)

// USER END

}

break;

case ID_DROPDOWN_0: // Notifications sent by 'Dropdown'

switch(NCode) {

case WM_NOTIFICATION_CLICKED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_RELEASED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_SEL_CHANGED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

// USER START (Optionally insert additional code for further notification handling)

// USER END

}

break;

// USER START (Optionally insert additional code for further Ids)

// USER END

}

break;

// USER START (Optionally insert additional message handling)

// USER END

default:

WM_DefaultProc(pMsg);

break;

}

}

/*********************************************************************

*

* Public code

*

**********************************************************************

*/

/*********************************************************************

*

* CreateFramewin

*/

WM_HWIN CreateFramewin(void);

WM_HWIN CreateFramewin(void) {

WM_HWIN hWin;

hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);

return hWin;

}

// USER START (Optionally insert additional public code)

// USER END

/*************************** End of file ****************************/代码里面写好了生成界面的代码,只需要在运行时调用最后的CreateFramewin函数就可以生成界面了。接下来我们看看模拟器的代码,是在GUIDEMO_Start.c这个文件里调用GUI_Init()和生成界面的函数的,想要运行我们刚刚的界面就需要在这个函数里调用CreateFramewin函数而不去调用官方的demo界面。GUIDEMO_Start.c内容如下:

代码语言:javascript代码运行次数:0运行复制/*********************************************************************

* SEGGER Microcontroller GmbH & Co. KG *

* Solutions for real time microcontroller applications *

**********************************************************************

* *

* (c) 1996 - 2015 SEGGER Microcontroller GmbH & Co. KG *

* *

* Internet: www.segger.com Support: support@segger.com *

* *

**********************************************************************

** emWin V5.32 - Graphical user interface for embedded applications **

emWin is protected by international copyright laws. Knowledge of the

source code may not be used to write a similar product. This file may

only be used in accordance with a license and should not be re-

distributed in any way. We appreciate your understanding and fairness.

----------------------------------------------------------------------

File : GUIDEMO_Start.c

Purpose : GUIDEMO initialization

----------------------------------------------------------------------

*/

#include "GUIDEMO.h"

/*********************************************************************

*

* MainTask

*/

void MainTask(void) {

#if GUI_WINSUPPORT

WM_SetCreateFlags(WM_CF_MEMDEV);

#endif

GUI_Init();

#if GUI_WINSUPPORT

WM_MULTIBUF_Enable(1);

#endif

GUIDEMO_Main();

}

/*************************** End of file ****************************/ 我们把除了MainTask函数以上的部分全部删除,替换为FramewinDLG.c文件里的内容,再对MainTask函数进行适当修改,如下:

代码语言:javascript代码运行次数:0运行复制/*********************************************************************

* *

* SEGGER Microcontroller GmbH & Co. KG *

* Solutions for real time microcontroller applications *

* *

**********************************************************************

* *

* C-file generated by: *

* *

* GUI_Builder for emWin version 5.24 *

* Compiled Jan 27 2014, 11:28:24 *

* (c) 2013 Segger Microcontroller GmbH & Co. KG *

* *

**********************************************************************

* *

* Internet: www.segger.com Support: support@segger.com *

* *

**********************************************************************

*/

// USER START (Optionally insert additional includes)

// USER END

#include "DIALOG.h"

/*********************************************************************

*

* Defines

*

**********************************************************************

*/

#define ID_FRAMEWIN_0 (GUI_ID_USER + 0x00)

#define ID_BUTTON_0 (GUI_ID_USER + 0x02)

#define ID_CHECKBOX_0 (GUI_ID_USER + 0x03)

#define ID_DROPDOWN_0 (GUI_ID_USER + 0x04)

// USER START (Optionally insert additional defines)

// USER END

/*********************************************************************

*

* Static data

*

**********************************************************************

*/

// USER START (Optionally insert additional static data)

// USER END

/*********************************************************************

*

* _aDialogCreate

*/

static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {

{ FRAMEWIN_CreateIndirect, "Framewin", ID_FRAMEWIN_0, 0, 0, 320, 240, 0, 0x64, 0 },

{ BUTTON_CreateIndirect, "Button", ID_BUTTON_0, 96, 24, 80, 20, 0, 0x0, 0 },

{ CHECKBOX_CreateIndirect, "Checkbox", ID_CHECKBOX_0, 97, 53, 80, 20, 0, 0x0, 0 },

{ DROPDOWN_CreateIndirect, "Dropdown", ID_DROPDOWN_0, 104, 90, 80, 19, 0, 0x0, 0 },

// USER START (Optionally insert additional widgets)

// USER END

};

/*********************************************************************

*

* Static code

*

**********************************************************************

*/

// USER START (Optionally insert additional static code)

// USER END

/*********************************************************************

*

* _cbDialog

*/

static void _cbDialog(WM_MESSAGE * pMsg) {

WM_HWIN hItem;

int NCode;

int Id;

// USER START (Optionally insert additional variables)

// USER END

switch (pMsg->MsgId) {

case WM_INIT_DIALOG:

//

// Initialization of 'Framewin'

//

hItem = pMsg->hWin;

FRAMEWIN_SetFont(hItem, GUI_FONT_32B_ASCII);

FRAMEWIN_SetText(hItem, "HelloWorld");

FRAMEWIN_SetTextAlign(hItem, GUI_TA_HCENTER | GUI_TA_VCENTER);

//

// Initialization of 'Checkbox'

//

hItem = WM_GetDialogItem(pMsg->hWin, ID_CHECKBOX_0);

CHECKBOX_SetText(hItem, "Check");

// USER START (Optionally insert additional code for further widget initialization)

// USER END

break;

case WM_NOTIFY_PARENT:

Id = WM_GetId(pMsg->hWinSrc);

NCode = pMsg->Data.v;

switch (Id) {

case ID_BUTTON_0: // Notifications sent by 'Button'

switch (NCode) {

case WM_NOTIFICATION_CLICKED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_RELEASED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

// USER START (Optionally insert additional code for further notification handling)

// USER END

}

break;

case ID_CHECKBOX_0: // Notifications sent by 'Checkbox'

switch (NCode) {

case WM_NOTIFICATION_CLICKED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_RELEASED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_VALUE_CHANGED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

// USER START (Optionally insert additional code for further notification handling)

// USER END

}

break;

case ID_DROPDOWN_0: // Notifications sent by 'Dropdown'

switch (NCode) {

case WM_NOTIFICATION_CLICKED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_RELEASED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

case WM_NOTIFICATION_SEL_CHANGED:

// USER START (Optionally insert code for reacting on notification message)

// USER END

break;

// USER START (Optionally insert additional code for further notification handling)

// USER END

}

break;

// USER START (Optionally insert additional code for further Ids)

// USER END

}

break;

// USER START (Optionally insert additional message handling)

// USER END

default:

WM_DefaultProc(pMsg);

break;

}

}

/*********************************************************************

*

* Public code

*

**********************************************************************

*/

/*********************************************************************

*

* CreateFramewin

*/

WM_HWIN CreateFramewin(void);

WM_HWIN CreateFramewin(void) {

WM_HWIN hWin;

hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);

return hWin;

}

// USER START (Optionally insert additional public code)

// USER END

/*************************** End of file ****************************/

/*********************************************************************

*

* MainTask

*/

void MainTask(void) {

#if GUI_WINSUPPORT

WM_SetCreateFlags(WM_CF_MEMDEV);

#endif

GUI_Init();

#if GUI_WINSUPPORT

WM_MULTIBUF_Enable(1);

#endif

//GUIDEMO_Main();

CreateFramewin();

while (1)

{

GUI_Delay(10);

}

}

/*************************** End of file ****************************/修改后运行就可以得到如下的结果了,是我们在GUIBuilder中设计的界面。

四、emWin查看器的使用 emWIn查看器和GUIBuilder都是在同一个目录下的,叫emWinView.exe,运行界面如下图所示:

无论我们emWin模拟器是先运行还是后运行,emWin查看器都可以捕捉到模拟器的运行画面。查看器上面有很多的功能可以使用,有助于调试,在多层显示的时候比较有用。

五、本文资料汇总链接:https://pan.baidu.com/s/1L6EZrFFqEyOFIoCrkOVpaQ 提取码:zi6r

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/182033.html原文链接:https://javaforall.cn

2025-08-10 21:35:51
紧急通知!!《钢铁战鹰》开测延期至7月11日
Steam 上的 MONSTER HUNTER RISE