完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
转stemwin教程
本期教程主要是跟大家讲一下STemWin多任务的设计,官方手册对于这部分内容在开头的时候讲的非常好,本期教程主要是把这部分内容给大家做个介绍,并在模拟器上跑一下多任务。 28. 1 单任务系统(超级循环) 28. 2 多任务系统:一个任务调用emWin 28. 3 多任务系统:多个任务调用emWin 28. 4 官方推荐运行方式 28. 5 运行多任务(模拟器) 28. 6 总结 28.1 单任务系统(超级循环) STemWin可以配置为不使用RTOS,这时就是整个程序在一个超循环中运行。通常,软件的所有组件都进行周期性调用。因为未使用实时内核,所以软件的实时部分必须使用中断。此类型系统主要用于小型系统,或者实时操作特性无关紧要时。平时大家写裸机程序的时候基本都是下面这种方式: [url=]复制代码[/url]
|
|
相关推荐
|
|
加入了STemWin的初始化函数后就是下面这样:
复制代码 void main (void) { /* 初始化硬件 */ HARDWARE_Init(); /* 初始化软件组件 */ XXX_Init(); YYY_Init(); GUI_Init(); //初始化emWin /* 超级循环: 规则的调用所以软件组件*/ while (1) { /* Exec all compontents of the software */ XXX_Exec(); YYY_Exec(); GUI_Exec(); //调用刷新函数 } } |
|
|
|
|
|
关于emWin的使用没有实际的限定。照例,需要在调用GUI_Init()之后才能使用该软件。之后,任何API函数都可使用。如果使用了窗口管理器的回调机制,则必须定期调用emWin更新函数。这通常通过从超循环内调用GUI_Exec()来完成。各种模块化函数,如GUI_Delay()和GUI_ExecDialog()不应在循环中使用,因为它们会阻断其它软件模块。可使用不支持多任务(#define GUI_OS 0)的默认配置;不需要内核接口例程。
l 优点 因为未使用实时内核 (->较小的ROM大小,仅一个堆栈->用于堆栈的RAM较少),所以不存在使用RTOS中的抢先/同步问题。 l 缺点 超循环类型程序的大小如果超出某个值,会变得很难维护。实时特性较差,因为一个软件组件无法被任何其它组件中断 (只能通过中断)。这意味着一个软件组件的反应时间取决于系统中所有其它组件的执行时间。 |
|
|
|
|
|
28.2 多任务系统:一个任务调用emWin
使用了实时内核(RTOS)。用户程序分成不同部分,在不同的任务中执行,这些任务通常具有不同的优先级。通常,实时关键任务 (需要一定的反应时间)将具有最高优先级。一个单任务用于用户界面,它调用emWin函数。此任务在系统中通常具有最低优先级,或至少是最低优先级任务中的一个(一些统计任务或简单的空闲时间处理可能具有更低的优先级)。中断可以但不是必须用于软件的实时部分。 如果使用了窗口管理器的回调机制,则必须从调用emWin的任务定期调用emWin更新函数(通常为GUI_Exec()、GUI_Delay())。 由 于emWin仅由一个任务调用,所以对于emWin而言,它与在单任务系统中的使用是相同的。可使用不支持多任务(#define GUI_OS 0)的默认配置;不需要内核接口例程。可使用任何实时内核,商用的或专用的。 l 优点 该系统的实时特性非常优秀。任务的实时特性仅受以较高优先级运行的任务的影响。这意味着对在低优先级任务中运行的程序组件的更改完全不会影响实时特性。如果从低优先级任务执行用户界面,则意味着用户界面的更改不影响实时特性。因此,使用这种系统可轻松将软件的不同组件分配给开发团队的不同成员,成员彼此间可以高度独立地工作。 l 缺点 用户需要拥有实时内核(RTOS),这需要资金并会耗费ROM和RAM(用于堆栈)。此外,还必须考虑任务的同步,以及如何将信息从一个任务传输到另一个任务。 |
|
|
|
|
|
28.3 多任务系统:多个任务调用emWin
使用了实时内核(RTOS)。用户程序分成不同部分,在不同任务中执行,这些任务通常具有不同的优先级。通常,实时关键任务 (需要一定的反应时间)将具有最高优先级。多个任务用于用户界面,调用emWin函数。这些任务在系统中通常具有低优先级,所以它们不影响系统的实时特性。中断可以但不是必须用于软件的实时部分。 如果使用了窗口管理器的回调机制,则必须从调用emWin的一个或多个任务定期调用emWin更新函数 (通常为GUI_Exec()、GUI_Delay())。不可使用不支持多任务(#define GUI_OS 0)的默认配置。配置需要启用多任务支持并定义从中调用emWin的任务的最大数目(摘自GUIConf.h): #define GUI_OS 1 // Enable multitasking support #define GUI_MAX_TASK 5 // Max. number of tasks that may call emWin 内核接口例程是必需的,并需要与正在使用的内核匹配。可使用任何实时内核,商用的或专用的。 l 优点 该系统的实时特性非常优秀。任务的实时特性仅受以较高优先级运行的任务的影响。这意味着对在低优先级任务中运行的程序组件的更改完全不会影响实时特性。如果从低优先级任务执行用户界面,则意味着用户界面的更改不影响实时特性。因此,使用这种系统可轻松将软件的不同组件分配给开发团队的不同成员,成员彼此间可以高度独立地工作。 l 缺点 用户必须拥有实时内核(RTOS),这需要资金并会耗费部分ROM和RAM(用于堆栈)。此外,还必须考虑任务的同步,以及如何将信息从一个任务传输到另一个任务。 |
|
|
|
|
|
28.4 官方推荐运行方式
上面介绍了三种STemWin的运行方式,下面介绍下官方推荐的运行方式: l 仅从一个任务调用emWin更新函数(即GUI_Exec()、GUI_Delay()),这有助于保持程序结构清晰。如果在您的系统中有足够的RAM,则指定一个任务(具有最低优先级)来更新emWin。如下面示例所示,此任务将不断调用GUI_Exec(),且不进行任何其它操作。 l 保持实时任务 (它们确定I/O、接口、网络等方面的系统特性)与调用emWin的任务分开,这有助于确保最佳的实时性能。 l 如果可能,仅为用户界面使用一个任务,这有助于保持程序结构简单并简化调试工作。(当然,这不是必须的,而且可能在一些系统中不适合。) 官方推荐的这几点比较的笼统,后面我会在教程中再跟大家详细讲解。 |
|
|
|
|
|
下面把相关的代码跟大家解释下:
复制代码 #ifndef SKIP_TEST #include #include "GUI.h" #include "FRAMEWIN.h" #if GUI_OS == 0 #error Multitasking sample requires task awareness (#define GUI_OS 1) #endif /******************************************************************* * * Define how to create a task and start multitasking * ******************************************************************** */ #ifndef WIN32 #include "RTOS.h" /* Definitions for embOS */ #define CREATE_TASK(pTCB, pName, pFunc, Priority, pStack) OS_CREATETASK(pTCB, pName, pFunc, Priority, pStack) #define START_MT() OS_Terminate(0) #define Delay(t) OS_Delay(t) #else #include "SIM.h" /* Definitions for the Win32 simulation */ #define CREATE_TASK(pTCB, pName, pFunc, Priority, pStack) SIM_CreateTask(pName, pFunc) #define START_MT() SIM_Start() #define Delay(t) SIM_Delay(t) #endif /******************************************************************* * * Static data * ******************************************************************** */ #ifndef WIN32 // // Stacks // static OS_STACKPTR int Stack_0[600]; static OS_STACKPTR int Stack_1[600]; static OS_STACKPTR int Stack_2[600]; static OS_TASK aTCB[3]; // Task control blocks #endif /******************************************************************* * * Static code * ******************************************************************** */ /******************************************************************* * * _cbCallbackT0 */ static int XPos; static const char aText[] = "Moving text..."; static void _cbCallbackT0(WM_MESSAGE * pMsg) {(1) switch (pMsg->MsgId) { case WM_PAINT: // // Handle the paint message // GUI_SetBkColor(GUI_RED); GUI_SetColor(GUI_BLACK); GUI_SetFont(&GUI_FontComic24B_ASCII); GUI_Clear(); GUI_DispStringAt(aText, XPos, 0); break; default: WM_DefaultProc(pMsg); } } /******************************************************************* * * _cbCallbackT1 */ static void _cbCallbackT1(WM_MESSAGE * pMsg) {(2) WM_HWIN hWin = (FRAMEWIN_Handle)(pMsg->hWin); switch (pMsg->MsgId) { case WM_PAINT: // // Handle the paint message // GUI_SetBkColor(GUI_BLUE); GUI_SetColor(GUI_WHITE); GUI_SetFont(&GUI_FontComic24B_ASCII); GUI_SetTextAlign(GUI_TA_HCENTER | GUI_TA_VCENTER); GUI_Clear(); GUI_DispStringHCenterAt("Moving window...", WM_GetWindowSizeX(hWin) / 2, WM_GetWindowSizeY(hWin) / 2); break; default: WM_DefaultProc(pMsg); } } /******************************************************************* * * _cbBackgroundWin */ static void _cbBackgroundWin(WM_MESSAGE* pMsg) {(3) switch (pMsg->MsgId) { case WM_PAINT: // // Handle only the paint message // GUI_SetBkColor(0x00CC00); GUI_Clear(); GUI_SetFont(&GUI_Font24_ASCII); GUI_DispStringHCenterAt("emWin - multitasking demon", 160, 5); GUI_SetFont(&GUI_Font13_1); GUI_DispStringAt("Scrolling text and moving windows without flickering", 5, 35); default: WM_DefaultProc(pMsg); } } /******************************************************************* * * _Task_0 */ static void _Task_0(void) {(4) // // Create frame window // FRAMEWIN_Handle hFrameWin = FRAMEWIN_Create("Task 0", NULL, WM_CF_SHOW | WM_CF_STAYONTOP, 0, 70, 200, 40); // // Create child window // WM_HWIN hChildWin = WM_CreateWindowAsChild(0, 0, 0, 0, WM_GetClientWindow(hFrameWin), WM_CF_SHOW | WM_CF_MEMDEV, _cbCallbackT0, 0); FRAMEWIN_SetActive(hFrameWin, 0); // // Make sure the right window is active... // WM_SelectWindow(hChildWin); // // ...and the right font is selected // GUI_SetFont(&GUI_FontComic24B_ASCII); while(1) { GUI_RECT Rect; int XLen; XLen = GUI_GetStringDistX(aText); // Get the length of the string WM_GetClientRect(&Rect); // Get the size of the window // // Show moving text // for (XPos = 0; XPos < (Rect.x1 - Rect.x0) - XLen; XPos++) { WM_InvalidateWindow(hChildWin); Delay(50); } for (; XPos >= 0; XPos--) { WM_InvalidateWindow(hChildWin); Delay(100); } } } /******************************************************************* * * _Task_1 */ static void _Task_1(void) {(5) // // Create frame window // FRAMEWIN_Handle hFrameWin = FRAMEWIN_Create("Task 1", NULL, WM_CF_SHOW | WM_CF_STAYONTOP, 20, 170, 200, 40); // // Create child window // WM_HWIN hChildWin = WM_CreateWindowAsChild(0, 0, 0, 0, WM_GetClientWindow(hFrameWin), WM_CF_SHOW | WM_CF_MEMDEV, _cbCallbackT1, 0); FRAMEWIN_SetActive(hFrameWin, 0); while(1) { int i; int nx = 80; int ny = 90; // // Move window continously // for (i = 0; i < ny; i++) { WM_MoveWindow(hFrameWin, 0, -2); Delay(50); } for (i = 0; i < nx; i++) { WM_MoveWindow(hFrameWin, 2, 0); Delay(50); } for (i = 0; i < ny; i++) { WM_MoveWindow(hFrameWin, 0, 2); Delay(50); } for (i = 0; i < nx; i++) { WM_MoveWindow(hFrameWin, -2, 0); Delay(50); } } } /******************************************************************* * * _GUI_Task * * This task does the background processing. * The MainTask job is to update invalid windows, but other things such as * evaluating mouse or touch input may also be done. */ static void _GUI_Task(void) {(6) while(1) { GUI_Exec(); // Do the background work ... Update windows etc.) GUI_X_ExecIdle(); // Nothing left to do for the moment ... Idle processing } } /********************************************************************* * * Public code * ********************************************************************** */ /********************************************************************* * * MainTask */ void MainTask(void) { // // Init GUI // GUI_Init(); WM_SetCreateFlags(WM_CF_MEMDEV); // Use memory devices on all windows to avoid flicker WM_SetCallback(WM_HBKWIN, _cbBackgroundWin); // Set callback for background window // // Create tasks // CREATE_TASK(&aTCB[0], "Task_0", _Task_0, 80, Stack_0);(7) CREATE_TASK(&aTCB[1], "Task_1", _Task_1, 60, Stack_1); CREATE_TASK(&aTCB[2], "GUI_TASK", _GUI_Task, 1, Stack_2); // // Start multitasking // START_MT(); } #endif |
|
|
|
|
|
跟大家讲这个DEMO,主要是想让大家对emWin的多任务框架有个了解,对于初学者可以不必了解主要是实现了什么功能。但必须得知道这个多任务实现的框架。
1. 任务0所创建窗口的回调函数。 2. 任务1所创建窗口的回调函数。 3. 桌面窗口的回调函数。 4. 任务0所跑的具体函数 5. 任务1所跑的具体函数。 6. 这个任务专门用emWin的刷新。 7. 创建三个任务。 |
|
|
|
|
|
飞凌嵌入式-ELFBOARD-RGB LCD屏接口的PCB设计要点
346 浏览 0 评论
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-spi编程示例之spi编写程序
786 浏览 0 评论
《DNK210使用指南 -CanMV版 V1.0》第三十七章 image图像对比实验
756 浏览 0 评论
961 浏览 1 评论
652 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11674 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-13 11:41 , Processed in 1.441679 second(s), Total 85, Slave 68 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号