一种简单的信号量实现:
void sem_init( volatile U08 *Sem )
{
(*Sem)=0;
}
void sem_post( volatile U08 *Sem )
{
if( 0 == (*Sem) )
(*Sem)++;
}
U08 sem_wait( volatile U08 *Sem )
{
if(0 == *Sem)
return 1;
(*Sem)--;
return 0;
}
在一个大的while(1)大循环中,利用信号量实现各个函数(任务)的同步。
void Task_SysTime( void )
{
static int TaskInitFlg = 0;
U32 Timer1sCount = 0; //时钟计数器个数
U32 disstat = 0;
static int tmrid0 = 0, tmrid1 = 0, tmrid2 = 0, tmrid3 = 0;
if( 0 == TaskInitFlg )
{
OSTimeDlyHMSM( 0, 0, 0, 50 //主要等待任务删除后才创建卡任务
tmrid0 = TimerSet(20); //定时器0(毫秒定时器)用于键盘、寻卡、定时器中断服务程序,20ms
tmrid1 = TimerSet(1000);//定时器1(毫秒定时器)用于背显、GPS、定时连接检测、空闲显示
tmrid2 = TimerSet(500); //定时器2(毫秒定时器)用于信号显示,500ms
tmrid3 = TimerSet(500); //定时器3(毫秒定时器)用于电池显示,500ms
sem_init( &gSem_EVT_CARDFLG_OK ); //初始化为没有卡
APP_DisIdle( 2 ); //显示一次时间
APP_DisVoice();
TaskInitFlg = 1; //任务初始化完成
}
else
{
HW_IWDG_ReloadCounter(); //清看门狗
if( 0 == TimerCheck(tmrid0) )
{
tmrid0 = TimerSet(20); //定时器0重新定时, 20ms
Timer_ScanKeyboard(); //20MS键盘扫描
Timer_FindCard(); //20MS寻卡处理
TIM20MS_IRQHandler(); //20MS定时器中断服务程序
}
}
}
void Task_Tick( void )
{
Task_SysError();
Task_CardProc();
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#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 更为巧妙的是,可以借住函数指针实现一种灵活的菜单和按键实时处理结构。
定义界面刷新显示和响应按键处理的结构:
#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);
#incl