Task_SysTime();
Task_MenuProc();
Task_MtnLink();
Task_CommProc();
}
int main( void )
{
Sys_Init(); //系统初始化
while( 1 )
{
Task_Tick(); //任务轮询
if( 0 == sem_wait( &gSem_EVT_QUIT_APP ) )
break; //应用退出
}
}
以上为借助信号量和定时器实现的一种简单的模拟多任务,其实也算不上是多任务,因为如果一个函数执行时间很长,如何打断它?
以下为借住定时器和任务队列实现的一种模拟多任务:
#include <stdio.h>
#include “timTask.h”
#include “disp.h”
/=====================================================
= 变量定义
=====================================================/
//任务队列
typedef struct{
char flagState; //运行方式 0: 无任务
// 1: 运行
char flagRun; //完成状态 0: 正在计数
// 1: 计数完成
char flagType; //处理方式 0: 主任务处理
// 1: 中断处理
ulong cntRun; //运行计数器
ulong numCircle; //循环计数器
void (*pTaskFunc)(void); //任务
}TypeTimTask;
TypeTimTask timTaskTab[TIM_TASK_NUMBER];
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
void TimTaskInit(void)
{
int i;for (i=0; i<TIM_TASK_NUMBER; i++)
{
timTaskTab[i].pTaskFunc = 0;
timTaskTab[i].cntRun = 0;
timTaskTab[i].numCircle = 0;
timTaskTab[i].flagRun = 0;
timTaskTab[i].flagState = 0;
}
SPT_register_call_back(TimTaskUpdate);
SPT_set(TIM_TASK_PERIOD *64 / 1000);
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
short TimTaskAdd(ulong fsttim, ulong cirtim, void (*pTaskFunc)(void), uchar type)
{
int i;
int pos = -1;
//查找位置
for (i=0; i<TIM_TASK_NUMBER; i++)
{
if (timTaskTab[i].pTaskFunc == pTaskFunc)
{
pos = i;
break;
}
if ((pos == -1) && (timTaskTab[i].flagState == 0))
{
pos = i;
}
}
//任务已满
if (pos == -1)
{
return -1;
}
//
timTaskTab[pos].pTaskFunc = pTaskFunc;
timTaskTab[pos].cntRun = fsttim / TIM_TASK_PERIOD;
timTaskTab[pos].numCircle = cirtim / TIM_TASK_PERIOD;
timTaskTab[pos].flagRun = 0;
timTaskTab[pos].flagType = type;
timTaskTab[pos].flagState = 1;return 0;
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
void TimTaskDel(void (*pTaskFunc)(void))
{
int i;for (i=0; i<TIM_TASK_NUMBER; i++)
{
if (timTaskTab[i].pTaskFunc == pTaskFunc)
{
timTaskTab[i].flagState = 0;
timTaskTab[i].flagRun = 0;
return;
}
}
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
void TimTaskUpdate(void)
{
int i;SPT_set(TIM_TASK_PERIOD *64 / 1000);
for (i=0; i<TIM_TASK_NUMBER; i++)
{
if (timTaskTab[i].flagState != 0)
{
if (timTaskTab[i].cntRun != 0)
{
timTaskTab[i].cntRun–;
}
else
{
//判断处理位置
if (timTaskTab[i].flagType != 0)
(*timTaskTab[i].pTaskFunc)();
else
timTaskTab[i].flagRun = 1;
//判断重载
if (timTaskTab[i].numCircle)
timTaskTab[i].cntRun = timTaskTab[i].numCircle;
else
timTaskTab[i].flagState = 0;
}
}
}
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
void TimTaskProc(void)
{
int i;for (i=0; i<TIM_TASK_NUMBER; i++)
{
if (timTaskTab[i].flagRun != 0)
{
timTaskTab[i].flagRun = 0;
(*timTaskTab[i].pTaskFunc)();
}
}
}
更为巧妙的是,可以借住函数指针实现一种灵活的菜单和按键实时处理结构。类似于windows下win32的消息驱动机制,
通过中断等方式把实时事件封装成消息。以下为定义界面刷新显示和响应按键处理的结构:
#ifndef _PAGE_H
#define _PAGE_H
#include “heads.h”
/*=====================================================
=====================================================/
typedef struct{
void ( OnPaint)(void);
void (* OnKey)(short);
}TypePage;
/*=====================================================
=====================================================*/
void WndPageSet(const TypePage *pg, int type = 0);
TypePage * WndGetPage(void);
void WndPageEsc(void);
void WndOnKey(short key);
void WndOnPaint(void);
void WndMenuInit(const char *pmn, char mline);
void WndMenuSelet(int m);
char WndMenuGetSelet(void);
long WndGetPaseword(int x, int y, char *psw, int len, long qevent);
#include “pageWnd.h”
/*=====================================================
=====================================================/
char flagPaint = 0;
void ( pOnPaint)(void) = 0;
void (* pOnKey)(short) = 0;
const char *pMenuStr;
uchar menuSelect = 0;
uchar menuLine = 0;
uchar menuTop;
TypePage *pageCurrent;
TypePage *pageTreeTab[10];
uchar pageIndex = 0;
/*=====================================================
=====================================================*/
void WndDrawMenu(void);
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
void WndPageSet(const TypePage *pg, int type)
{
if (pg == &pageMain) //防止出错
{
pageIndex = 0;
}
else if (type == 0)
{
pageTreeTab[pageIndex++] = pageCurrent;
}
pageCurrent = (TypePage *)pg;
pOnPaint = pg->OnPaint;
pOnKey = pg->OnKey;
flagPaint = 1;
}
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
TypePage * WndGetPage(void)
{
return pageCurrent;
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
void WndPageEsc(void)
{
TypePage *pg;if (pageIndex != 0)
{
pageIndex–;
pg = pageTreeTab[pageIndex];
}
else
{
pg = (TypePage *)&pageMain;
}
pageCurrent = pg;
pOnPaint = pg->OnPaint;
pOnKey = pg->OnKey;
flagPaint = 1;
}
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
void WndOnPaint(void)
{
if (flagPaint != 0)
{
flagPaint = 0;
(*pOnPaint)();
}
}
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
void WndOnKey(short key)
{
if (pOnKey != 0)
{
(*pOnKey)(key);
}
}
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
void WndMenuInit(const char *pmn, char mline)
{
menuSelect = 0;
pMenuStr = pmn;
menuLine = mline;
menuTop = 0;
WndDrawMenu();
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
void WndMenuSelet(int m)
{
//光标滑动
if (m > 0) //下移
{
menuSelect++;
if (menuSelect == menuLine)
menuSelect = 0;if (menuSelect > menuTop + 4) { if (menuLine < menuTop + 4) menuTop = menuLine - 4; else menuTop = menuSelect - 4; }
}
else if (m < 0) //上移
{
if (menuSelect == 0)
menuSelect = menuLine - 1;
else
menuSelect–;
}
//图框移动
if (menuSelect < menuTop) //上移
{
menuTop = menuSelect;
}
else if (menuSelect >= menuTop + 4) //下移
{
menuTop = menuSelect - 3;
}WndDrawMenu();
}
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
char WndMenuGetSelet(void)
{
return menuSelect + 1;
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
void WndDrawMenu(void)
{
int i;char buf[17];
const char *pmn = pMenuStr + menuTop * 16;DispClr();
for (i=0; i<4; i++)
{
if (menuTop + i == menuLine)
break;
memcpy(buf, pmn, 16);
buf[16] = ‘\0’;
if (menuSelect == menuTop + i)
DispSetStyle(DISP_POSITION | DISP_REVERSE | DISP_7x9);
else
DispSetStyle(DISP_POSITION | DISP_NORMAL | DISP_7x9);
DispString(0, i * 2, buf);
pmn += 16;
}
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
long WndGetPaseword(int x, int y, char *psw, int len, long qevent)
{
int pin = 0;
long keyevt;
char key;
char buf[20];memset(buf, ‘', len);
buf[len] = ‘\0’;
PSW_INPUT_LOOP:
DispString(x, y, buf);
keyevt = delay_and_wait_key(0, EXIT_KEY_ALL, 0);
if (keyevt == qevent)
{
psw[0] = ‘\0’;
return keyevt;
}
switch (keyevt)
{
case EXIT_KEY_0:
key = ‘0’;
break;
case EXIT_KEY_1:
key = ‘1’;
break;
case EXIT_KEY_2:
key = ‘2’;
break;
case EXIT_KEY_3:
key = ‘3’;
break;
case EXIT_KEY_4:
key = ‘4’;
break;
case EXIT_KEY_5:
key = ‘5’;
break;
case EXIT_KEY_6:
key = ‘6’;
break;
case EXIT_KEY_7:
key = ‘7’;
break;
case EXIT_KEY_8:
key = ‘8’;
break;
case EXIT_KEY_9:
key = ‘9’;
break;
case EXIT_KEY_COMM:
if (pin != 0)
{
buf[–pin] = '’;
}
goto PSW_INPUT_LOOP;
break;
case EXIT_KEY_ENTER:
psw[pin] = 0;
return 0;
default:
goto PSW_INPUT_LOOP;
}
if (pin != len)
{
psw[pin] = key;
buf[pin] = ‘*’;
pin++;
}
goto PSW_INPUT_LOOP;
}
在软件设计时,如果添加界面和对应的按键处理,很灵活,只需要新添加一个文件就可以了,文件的内容,只需要实现OnPain和对应的OnKey
#include “PageMenu.h”
/*=====================================================
=====================================================/
const char mainMenuTab[] = /
1234567890123456*/"\
- 现场采集 \
- 数据上传 \
- 存储状态查询 \
- 时间设置 \
- 对比度设置 \
- 恢复出厂设置 \
- 关于 ";
/*=====================================================
=====================================================*/
void PageMenuOnPain(void);
void WndMenuOnKey(short key);
const TypePage pageMenu = {PageMenuOnPain, WndMenuOnKey};
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
void PageMenuOnPain(void)
{
WndMenuInit(mainMenuTab, 7);
}
/*************************************************************************
-
函数原型:
-
功能描述:
-
入口参数:
-
出口参数:
-
返 回 值:
*************************************************************************/
void WndMenuOnKey(short key)
{
int res;switch (key)
{
case KEY_F1:
case KEY_ENTER:
res = WndMenuGetSelet();
switch (res)
{
case 1:
WndPageSet(&pageSimp);
break;
case 2:
WndPageSet(&pagePclink);
break;
case 3:
WndPageSet(&pageInquire);
break;
case 4:
WndPageSet(&pageRtc);
break;
case 5:
WndPageSet(&pageGray);
break;
case 6:
SPageInit();
WndPageSet(&pageMenu, 1);
break;
case 7:
WndPageSet(&pageAbout);
break;
}
break;
case KEY_F2:
case KEY_F3:
WndPageSet(&pageMain);
break;
case KEY_1:
WndPageSet(&pageSimp);
break;
case KEY_2:
WndPageSet(&pagePclink);
break;
case KEY_3:
WndPageSet(&pageInquire);
break;
case KEY_4:
WndPageSet(&pageRtc);
break;
case KEY_5:
WndPageSet(&pageGray);
break;
case KEY_6:
SPageInit();
WndPageSet(&pageMenu, 1);
break;
case KEY_7:
WndPageSet(&pageAbout);
break;
case KEY_UP:
WndMenuSelet(-1);
break;
case KEY_DOWN:
WndMenuSelet(1);
break;
case KEY_POWER:
WndPageSet(&pagePower);
break;
}
}
pageMain,pageAbout,pageRtc,pagePclink等文件,他们的结构很类似。都是实现了OnPaint和OnKey函数。
如:pagePclink.c文件内容:
实现了PagePclinkOnPaint和PagePclinOnKey函数.
CommPclink函数是自己想要实现的功能,可以自己定义。
#include “pagePclink.h”
/*=====================================================
=====================================================*/
void PagePclinkOnPaint(void);
void PagePclinOnKey(short key);
const TypePage pagePclink = {PagePclinkOnPaint, PagePclinOnKey};
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
void PagePclinkOnPaint(void)
{
DispClr();
DispSetStyle(DISP_CENTER | DISP_REVERSE | DISP_7x9);
DispString(0, 0, " 数据上传 ");
DispSetStyle(DISP_POSITION|DISP_NORMAL|DISP_7x9);
DispString(0, 6, “[连接] [返回]”);
}
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
void PagePclinOnKey(short key)
{
switch (key)
{
case KEY_F1:
CommPclink();
break;
case KEY_F3:
WndPageEsc();
break;
}
}
#ifndef _PAGE_POWER_H
#define _PAGE_POWER_H
#include “pageWnd.h”
/*=====================================================
=====================================================*/
extern const TypePage pagePower;
#endif
#include “PagePower.h”
#include “disp.h”
/*=====================================================
=====================================================*/
void PagePowerOnPaint(void);
void PagePowerOnKey(short key);
const TypePage pagePower = {PagePowerOnPaint, PagePowerOnKey};
/*************************************************************************
- 函数原型:
- 功能描述:
- 入口参数:
- 出口参数:
- 返 回 值:
*************************************************************************/
void PagePowerOnPaint(void)
{
DispClr();
DispSetStyle(DISP_CENTER | DISP_REVERSE | DISP_7x9);
DispString(0, 0, " 电源管理 ");