在有嵌入式操作系统的情况下,可以利用多任务和信号量,事件等设计嵌入式软件。但是在没有操作系统的裸机中,更需要有好的架构。例如利用事件和状态机模拟实现多任务,或者利用定时器和消息队列,信号量等模拟实现多任务,有了多任务就能灵活的设计软件架构。
借住定时器和任务队列实现的一种模拟多任务:
#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的消息驱动机制,
通过中断等方式把实时事件封装成消息。以下为定义界面刷新显示和响应按键处理的结构: