加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【STemWin教程入门篇】第29章 STemWin多任务(uCOS-III)

(2015-02-11 15:08:16)
标签:

多任务

ucos-iii

ucgui

emwin

dsp

分类: emWin
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接

第29章  STemWin多任务(uCOS-III)

本期教程主要是在开发板实现上期教程中所说的三种系统。这里大家重点学习一下官方推荐的设计框架即可,如果有不懂的函数会在后面跟大家讲。

29.  单任务系统(超级循环)

29. 多任务系统:一个任务调用emWin

29. 多任务系统:多个任务调用emWin

29. 总结

29.1  单任务系统(超级循环)

工程代码的结构如下:

【STemWin教程入门篇】第29章 <wbr>STemWin多任务(uCOS-III)

关于移植的知识已经在前面的第二章详细讲解了,这里重点介绍时间框架和接口函数。

29.1.1 内核接口

内核接口文件GUI_X.C内容如下:

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

File        GUI_X.C

Purpose     Config System dependent externals for GUI

---------------------------END-OF-HEADER------------------------------

*/

 

#include "GUI.h"

#include "stm32f4xx.h"

 

 

 

 

extern __IO int32_t g_iRunTime;(1)

int GUI_X_GetTime(void)(2)

{

 

return g_iRunTime;

}

 

void GUI_X_Delay(int ms)(3)

{

int tEnd g_iRunTime ms;

while ((tEnd g_iRunTime) 0);

}

 

 

 

void GUI_X_Init(void) {}

 

 

 

 

void GUI_X_ExecIdle(void) {}

 

 

 

void GUI_X_Log     (const char *s) GUI_USE_PARA(s); }

void GUI_X_Warn    (const char *s) GUI_USE_PARA(s); }

void GUI_X_ErrorOut(const char *s) GUI_USE_PARA(s); }

1. 时间基准全局变量,这个变量在bsp_timer.c文件里面进行了定义,由嘀嗒定时器中断进行调用,每1ms调用一次。

 

 

__IO int32_t g_iRunTime 0;

 

void SysTick_ISR(void)

{

static uint8_t s_count 0;

uint8_t i;

 

 

if (s_uiDelayCount 0)

{

if (--s_uiDelayCount == 0)

{

s_ucTimeOutFlag 1;

}

}

 

 

for (i 0; TMR_COUNT; i++)

{

bsp_SoftTimerDec(&s_tTmr[i]);

}

 

 

g_iRunTime++;

if (g_iRunTime == 0x7FFFFFFF)

{

g_iRunTime 0;

}

 

bsp_RunPer1ms();

 

if (++s_count >= 10)

{

s_count 0;

 

bsp_RunPer10ms();

}

}

2. 供STemWin调用的接口函数,用于获取系统时钟基准。

3. 供STemWin调用的接口函数,用于延迟时间设置。

4. 主要设置上面两个函数即可,其余函数根据需要进行配置。

29.1.2 触摸接口

触摸部分由嘀嗒定时器中周期性的调用:

 

extern __IO uint8_t s_ucRA8875BusyNow;

void bsp_RunPer10ms(void)

{

 

if (g_ChipID == IC_8875)

{

    

if(s_ucRA8875BusyNow == 0)

{

GUI_TOUCH_Exec();

}

}

 

else

{

GUI_TOUCH_Exec();

}

 

}

29.1.3 主程序

在文件main.c

 

int main(void)

{

 

bsp_Init();

 

MainTask();

}

在文件MainTask.c

 

void MainTask(void) 

{

int xPos;

int yPos;

int xSize;

int i;

 

0;

 

 

GUI_Init();

 

 

xPos LCD_GetXSize() 2; 

yPos LCD_GetYSize() 3;

 

 

GUI_SetTextMode(GUI_TM_REV);

 

 

GUI_SetFont(GUI_FONT_20F_ASCII);

GUI_DispStringHCenterAt("Hello world!", xPos, yPos);

 

 

GUI_SetFont(GUI_FONT_D24X32);

 

xSize GUI_GetStringDistX("0000");

 

 

xPos -= xSize 2;

yPos += 24 10;

while (1) 

{

GUI_DispDecAt( i++, xPos, yPos, 4);

if (i 9999) 

{

0;

}

}

}

 

功能比较简单,实现效果如下:

【STemWin教程入门篇】第29章 <wbr>STemWin多任务(uCOS-III)

29.2  多任务系统:一个任务调用emWin

前面几期教程配套的例子都是采用的这种方式,实现这种方式也是分为三部分

29.2.1 内核接口

内核接口文件GUI_X.C内容如下:

#include 

#include 

#include "GUI_Private.H"

#include "stdio.H"

 

 

 

static  OS_SEM  DispSem;

static  OS_SEM  EventSem;

 

static  OS_SEM  KeySem;

static  int     KeyPressed;

static  char    KeyIsInited;

 

 

 

 

int  GUI_X_GetTime (void) (1)

{

    OS_ERR      err;

return OSTimeGet(&err);

}

 

 

void  GUI_X_Delay (int period) (2)

{

  OS_ERR      err;

  OSTimeDly(period, OS_OPT_TIME_DLY, &err);

}

 

 

 

void GUI_X_ExecIdle (void) (3)

{

    GUI_X_Delay(1);

}

 

 

 

 

void  GUI_X_InitOS (void)(4)

OS_ERR     err;

 

 

    OSSemCreate((OS_SEM    *)&DispSem,

                (CPU_CHAR  *)"DispSem",

                (OS_SEM_CTR )1,

                (OS_ERR    *)&err);

 

OSSemCreate((OS_SEM    *)&EventSem,

                (CPU_CHAR  *)"EventSem",

                (OS_SEM_CTR )0,

                (OS_ERR    *)&err);

}

 

void  GUI_X_Lock (void)(5)

OS_ERR     err;

 

OSSemPend((OS_SEM *)&DispSem,

  (OS_TICK )0,

  (OS_OPT  )OS_OPT_PEND_BLOCKING,

  (CPU_TS  )0,

  (OS_ERR *)&err);

}

 

void  GUI_X_Unlock (void)(6)

OS_ERR     err;

 

OSSemPost((OS_SEM *)&DispSem,

          (OS_OPT  )OS_OPT_POST_1,

          (OS_ERR *)&err);

}

 

 

U32  GUI_X_GetTaskId (void) (7)

    //由于存在同优先级的任务,这里不知道是不是可以

//uCOS-III中已经没有任务的ID

return ((U32)(OSTCBCurPtr->Prio));

}

 

 

 

 

void GUI_X_WaitEvent (void) (8)

{

OS_ERR     err;

 

OSSemPend((OS_SEM *)&EventSem,

(OS_TICK )0,

(OS_OPT  )OS_OPT_PEND_BLOCKING,

(CPU_TS  )0,

(OS_ERR *)&err);

}

 

 

void GUI_X_SignalEvent (void) (9)

{

OS_ERR     err;

 

OSSemPost((OS_SEM *)&EventSem,

      (OS_OPT  )OS_OPT_POST_1,

      (OS_ERR *)&err);

}

 

 

 

void  CheckInit (void) (10)

{

if (KeyIsInited == DEF_FALSE) {

KeyIsInited DEF_TRUE;

GUI_X_Init();

}

}

 

void GUI_X_Init (void) 

{

OS_ERR err;

 

OSSemCreate((OS_SEM    *)&KeySem,

(CPU_CHAR  *)"KeySem",

(OS_SEM_CTR )0,

(OS_ERR    *)&err);

}

 

int  GUI_X_GetKey (void) 

{

int r;

 

         KeyPressed;

CheckInit();

KeyPressed 0;

return (r);

}

 

int  GUI_X_WaitKey (void) 

{

int    r;

OS_ERR err;

 

 

CheckInit();

if (KeyPressed == 0)   

OSSemPend((OS_SEM *)&EventSem,

(OS_TICK )0,

(OS_OPT  )OS_OPT_PEND_BLOCKING,

(CPU_TS  )0,

(OS_ERR *)&err);

}

         KeyPressed;

KeyPressed 0;

return (r);

}

 

void  GUI_X_StoreKey (int k) 

{

OS_ERR     err;

 

KeyPressed k;

OSSemPost((OS_SEM *)&KeySem,

      (OS_OPT  )OS_OPT_POST_1,

      (OS_ERR *)&err);

}

 

void GUI_X_Log     (const char *s) GUI_USE_PARA(s); }(11)

void GUI_X_Warn    (const char *s) GUI_USE_PARA(s); }

void GUI_X_ErrorOut(const char *s) GUI_USE_PARA(s); }

1. 用于给系统提供时间基准。

2. 用于实现延迟。

3. 用于执行空闲的调用。

4. 创建两个信号量,一个用于资源的共享,另一个用于事件的同步。

5. 这个函数用于锁定GUI,此函数在GUI访问显示器之前或在使用关键内部数据结构之前由GUI调用,它使用资源信号量/互斥体阻止其它线程进入同一临界区,直到GUI_X_Unlock()已被调用。

6. 这个函数用于解锁GUI,此函数在访问显示器之后或在使用关键内部数据结构之后由GUI调用。在使用实时操作系统时,通常必须减量计数资源信号量。

7. 用于返回当前任务的唯一ID。只要返回值对于使用emWin API的每个任务/线程是唯一的,且只要该值对于每个特定线程始终相同,则返回值是多少并不重要。

8. 用于等待事件。

9. 用于释放事件。

10. 这个里面的几个函数用实现按键接口函数。通过创建信号量来实现同步功能。

11. 这三个函数用调试目的。

29.2.2 触摸任务

 

 

extern __IO uint8_t s_ucRA8875BusyNow;

static void AppTaskGUIRefresh(void *p_arg)

{

    (void)p_arg;

 

while (1) 

{

 

if (g_ChipID == IC_8875)

{

    

if(s_ucRA8875BusyNow == 0)

{

GUI_TOUCH_Exec();

}

}

 

else

{

GUI_TOUCH_Exec();

}

 

BSP_OS_TimeDlyMs(20); 

}

}

29.2.3 STemWin任务

 

void MainTask(void) 

{

    GUI_Init();

    GUI_SetTextMode(GUI_TM_TRANS);

    for (i 0; 3; i++) 

    {

        GUI_SetColor(GUI_BLUE);

        GUI_FillRectEx(&Rect);

        GUI_SetColor(GUI_WHITE);

        GUI_DispStringInRectWrap(acText, &Rect, GUI_TA_LEFT, aWm[i]);

        Rect.x0 += 60;

        Rect.x1 += 60;

    }

    while (1)

    {

        GUI_Delay(10);

    }

}

这个例子整体的显示效果如下:

【STemWin教程入门篇】第29章 <wbr>STemWin多任务(uCOS-III)

29.3  多任务系统:多个任务调用emWin

这个例子也是分为三部分,内核接口和触摸任务跟上面讲的一样,这里主要说一下创建的三个GUI任务。

29.3.1 uCOS创建三个STemWin任务

这三个任务在main.c函数里面创建,三个任务的优先级看相应注释

 

extern void MainTask(void);

static void AppTask0GUI(void *p_arg)

{

    (void)p_arg;

 

while (1) 

{

MainTask();

}

}

 

 

extern void Task_1(void);

static void AppTask1GUI(void *p_arg)

{

    (void)p_arg;

 

while (1) 

{

Task_1();

}

}

 

 

extern void Task_2(void);

static void AppTask2GUI(void *p_arg)

{

    (void)p_arg;

 

while (1) 

{

Task_2();

}

}

29.3.2 STemWin任务

建立的三个任务所在文件夹:

【STemWin教程入门篇】第29章 <wbr>STemWin多任务(uCOS-III)

MainTask文件中的任务:

#include "includes.h"

#include "MainTask.h"

 

 

 

static void _cbCallbackT0(WM_MESSAGE pMsg) 

{

switch (pMsg->MsgId) 

{

case WM_PAINT:

 

GUI_SetBkColor(GUI_RED);

GUI_SetColor(GUI_BLACK);

GUI_SetFont(&GUI_FontComic24B_ASCII);

GUI_Clear();

GUI_DispStringAt("Task0 Moving", 0, 0);

break;

default:

WM_DefaultProc(pMsg);

}

}

 

 

static void _cbBackgroundWin(WM_MESSAGE* pMsg) 

{

switch (pMsg->MsgId) 

{

case WM_PAINT:

 

GUI_SetBkColor(0x00CC00);

GUI_Clear();

GUI_SetFont(&GUI_Font24_ASCII);

GUI_DispStringHCenterAt("STemWin multitasking demo\n", 159, 5);

GUI_SetFont(&GUI_Font13_1);

GUI_DispStringAt("Scrolling text and moving windows without flickering", 5, 35);

default:

WM_DefaultProc(pMsg);

}

}

 

 

void Task_0(void) 

{

 

FRAMEWIN_Handle hFrameWin FRAMEWIN_Create("Task 0",  NULL, WM_CF_SHOW WM_CF_STAYONTOP,  0, 230, 200,

 40);

 

 

WM_HWIN      hChildWin WM_CreateWindowAsChild(0, 0, 0, 0, WM_GetClientWindow(hFrameWin), 

  WM_CF_SHOW WM_CF_MEMDEV,  _cbCallbackT0, 0);

FRAMEWIN_SetActive(hFrameWin, 0);

 

 

WM_SelectWindow(hChildWin);

 

 

GUI_SetFont(&GUI_FontComic24B_ASCII);

while(1) 

{

int i;

int nx 80;

 

 

for (i 0; nx; i++) 

{

WM_MoveWindow(hFrameWin, 2, 0);

GUI_Delay(50);

}

for (i 0; nx; i++) 

{

WM_MoveWindow(hFrameWin, -2, 0);

GUI_Delay(50);

}

}

 

}

 

 

void MainTask(void) 

GUI_Init();

WM_SetCreateFlags(WM_CF_MEMDEV);              

WM_SetCallback(WM_HBKWIN, _cbBackgroundWin); 

 

while(1)

{

Task_0();

}

}

App_Task1中的内容:

#include "includes.h"

#include "MainTask.h"

 

 

 

static void _cbCallbackT1(WM_MESSAGE pMsg) 

{

WM_HWIN hWin (FRAMEWIN_Handle)(pMsg->hWin);

switch (pMsg->MsgId) 

{

case WM_PAINT:

 

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("Task1 window...", 

WM_GetWindowSizeX(hWin) 2, 

WM_GetWindowSizeY(hWin) 2);

break;

default:

WM_DefaultProc(pMsg);

}

}

 

 

void Task_1(void) 

{

 

FRAMEWIN_Handle hFrameWin FRAMEWIN_Create("Task 1", NULL, WM_CF_SHOW WM_CF_STAYONTOP, 

20, 170, 200, 40);

 

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;

 

 

for (i 0; ny; i++) 

{

WM_MoveWindow(hFrameWin, 0, -2);

GUI_Delay(50);

}

 

for (i 0; nx; i++) 

{

WM_MoveWindow(hFrameWin, 2, 0);

GUI_Delay(50);

}

 

for (i 0; ny; i++) 

{

WM_MoveWindow(hFrameWin, 0, 2);

GUI_Delay(50);

}

 

for (i 0; nx; i++) 

{

WM_MoveWindow(hFrameWin, -2, 0);

GUI_Delay(50);

}

}

}

App_Task2中的内容:

#include "includes.h"

#include "MainTask.h"

 

 

static void _cbCallbackT2(WM_MESSAGE pMsg) 

{

switch (pMsg->MsgId) 

{

case WM_PAINT:

 

GUI_SetBkColor(GUI_YELLOW);

GUI_SetColor(GUI_BLACK);

GUI_SetFont(&GUI_FontComic24B_ASCII);

GUI_Clear();

GUI_DispStringAt("Task2 Moving", 0, 0);

break;

default:

WM_DefaultProc(pMsg);

}

}

 

 

void Task_2(void) 

{

 

FRAMEWIN_Handle hFrameWin FRAMEWIN_Create("Task 2",  NULL, WM_CF_SHOW WM_CF_STAYONTOP,  0, 190, 200, 40);

 

 

WM_HWIN         hChildWin WM_CreateWindowAsChild(0, 0, 0, 0, WM_GetClientWindow(hFrameWin), 

 WM_CF_SHOW WM_CF_MEMDEV,  _cbCallbackT2, 0);

FRAMEWIN_SetActive(hFrameWin, 0);

 

 

WM_SelectWindow(hChildWin);

 

 

GUI_SetFont(&GUI_FontComic24B_ASCII);

 

while(1) 

{

int i;

int nx 80;

 

 

for (i 0; nx; i++) 

{

WM_MoveWindow(hFrameWin, 2, 0);

GUI_Delay(50);

}

for (i 0; nx; i++) 

{

WM_MoveWindow(hFrameWin, -2, 0);

GUI_Delay(50);

}

}

}

这个例子的整体显示效果如下:

【STemWin教程入门篇】第29章 <wbr>STemWin多任务(uCOS-III)

29.4  总结

本期教程就跟大家讲这么多,希望通过创建的这三个DEMO让大家对STemWin创建裸机或者多任务系统有个整体认识,具体工程中用那种方式要根据实际的需求来决定。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有