1)使用信号量
#define TASK_STK_SIZE 512 /* 每个任务堆栈的大小(以字计算)*/ #define N_TASKS 10 /* 任务数*/ OS_STK TaskStk[N_TASKS][TASK_STK_SIZE]; /*任务堆栈*/ OS_STK TaskStartStk[TASK_STK_SIZE]; //开始任务的堆栈 char TaskData[N_TASKS]; /*传给每个任务的数据*/ OS_EVENT *RandomSem; //互斥型信号量 void main (void) { PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); /*清空屏幕*/ OSInit(); /* 初始化uC/OS-II*/ PC_DOSSaveReturn(); /* 保存环境以便稍后可以返回DOS环境*/ PC_VectSet(uCOS, OSCtxSw); /*设置uC/OS-II的切换处理函数*/ RandomSem = OSSemCreate(1); /* 建立一个信号量*/ OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);//创建第一个任务,优先级设置为最大值 OSStart(); /* 开始多任务*/ } void TaskStart (void *pdata) { #if OS_CRITICAL_METHOD == 3 /* 为CPU的状态寄存器分配内存*/ OS_CPU_SR cpu_sr; #endif char s[100]; INT16S key; pdata = pdata; /* 这步是为了防止编译错误*/ TaskStartDispInit(); /* 初始化显示屏*/ OS_ENTER_CRITICAL(); PC_VectSet(0x08, OSTickISR); /*替换机器的时钟中断函数为uC/OS-II所需要的中断函数*/ PC_SetTickRate(OS_TICKS_PER_SEC); /* 调整时钟频率*/ OS_EXIT_CRITICAL(); OSStatInit(); /* 初始化统计任务*/ TaskStartCreateTasks(); /*创建其他任务*/ for (;;) { TaskStartDisp(); if (PC_GetKey(&key) == TRUE) { /* 是否按键*/ if (key == 0x1B) { /* ESCAPE按下了*/ PC_DOSReturn(); /* 返回DOS*/ } } OSCtxSwCtr = 0; /* 切换次数计数器清零*/ OSTimeDlyHMSM(0, 0, 1, 0); /*挂起秒,让给其他任务运行*/ } } static void TaskStartCreateTasks (void) { INT8U i; for (i = 0; i < N_TASKS; i++) { /* 创建N_TASKS个任务*/ TaskData[i] = '0' + i; /* 每个任务显示其数据*/ OSTaskCreate(Task, (void *)&TaskData[i], &TaskStk[i][TASK_STK_SIZE - 1], i + 1); } } void Task (void *pdata) { INT8U x; INT8U y; INT8U err; for (;;) { OSSemPend(RandomSem, 0, &err); /* 获取信号量*/ x = random(80); /* 计算X坐标*/ y = random(16); /* 计算Y坐标*/ OSSemPost(RandomSem); /* 释放信号量*/ /* Display the task number on the screen */ PC_DispChar(x, y + 5, *(char *)pdata, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY); OSTimeDly(1); /* 挂起秒,让给其他任务运行*/ } }
2)使用消息邮箱
#define TASK_STK_SIZE 512 #define TASK_START_ID 0 /* 任务ID*/ #define TASK_CLK_ID 1 #define TASK_1_ID 2 #define TASK_2_ID 3 #define TASK_3_ID 4 #define TASK_4_ID 5 #define TASK_5_ID 6 #define TASK_START_PRIO 10 /* 任务优先级*/ #define TASK_CLK_PRIO 11 #define TASK_1_PRIO 12 #define TASK_2_PRIO 13 #define TASK_3_PRIO 14 #define TASK_4_PRIO 15 #define TASK_5_PRIO 16 OS_STK TaskStartStk[TASK_STK_SIZE]; OS_STK TaskClkStk[TASK_STK_SIZE]; OS_STK Task1Stk[TASK_STK_SIZE]; OS_STK Task2Stk[TASK_STK_SIZE]; OS_STK Task3Stk[TASK_STK_SIZE]; OS_STK Task4Stk[TASK_STK_SIZE]; OS_STK Task5Stk[TASK_STK_SIZE]; OS_EVENT *AckMbox; /* 任务和使用的消息邮箱*/ OS_EVENT *TxMbox; void main (void) { OS_STK *ptos; OS_STK *pbos; INT32U size; PC_DispClrScr(DISP_FGND_WHITE); OSInit(); PC_DOSSaveReturn(); PC_VectSet(uCOS, OSCtxSw); PC_ElapsedInit(); ptos = &TaskStartStk[TASK_STK_SIZE - 1]; pbos = &TaskStartStk[0]; size = TASK_STK_SIZE; OSTaskStkInit_FPE_x86(&ptos, &pbos, &size); OSTaskCreateExt(TaskStart, (void *)0, ptos, TASK_START_PRIO, TASK_START_ID, pbos, size, (void *)0, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSStart(); } void TaskStart (void *pdata) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif INT16S key; pdata = pdata; TaskStartDispInit(); OS_ENTER_CRITICAL(); PC_VectSet(0x08, OSTickISR); PC_SetTickRate(OS_TICKS_PER_SEC); OS_EXIT_CRITICAL(); OSStatInit(); AckMbox = OSMboxCreate((void *)0); /* 创建两个消息邮箱*/ TxMbox = OSMboxCreate((void *)0); TaskStartCreateTasks(); for (;;) { TaskStartDisp(); if (PC_GetKey(&key)) { if (key == 0x1B) { PC_DOSReturn(); } } OSCtxSwCtr = 0; OSTimeDly(OS_TICKS_PER_SEC); } } void Task1 (void *pdata) { INT8U err; OS_STK_DATA data; /* 任务堆栈数据*/ INT16U time; INT8U i; char s[80]; pdata = pdata; for (;;) { for (i = 0; i < 7; i++) { PC_ElapsedStart(); err = OSTaskStkChk(TASK_START_PRIO + i, &data);//执行堆栈检查 time = PC_ElapsedStop(); if (err == OS_NO_ERR) { sprintf(s, "%4ld %4ld %4ld %6d", data.OSFree + data.OSUsed, data.OSFree, data.OSUsed, time); PC_DispStr(19, 12 + i, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY); } } OSTimeDlyHMSM(0, 0, 0, 100); /* 挂起mS*/ } } void Task4 (void *data) { char txmsg; INT8U err; data = data; txmsg = 'A'; for (;;) { OSMboxPost(TxMbox, (void *)&txmsg); /* 发消息给Task #5*/ OSMboxPend(AckMbox, 0, &err); /* 等待Task #5的应答消息*/ txmsg++; /*下一个要发的消息数据*/ if (txmsg == 'Z') { txmsg = 'A'; /* 循环发送A-Z*/ } } } void Task5 (void *data) { char *rxmsg; INT8U err; data = data; for (;;) { rxmsg = (char *)OSMboxPend(TxMbox, 0, &err); /* 等待来自Task #4的数据*/ PC_DispChar(70, 18, *rxmsg, DISP_FGND_YELLOW + DISP_BGND_BLUE); OSTimeDlyHMSM(0, 0, 1, 0); /* 挂起秒,让给其他任务运行*/ OSMboxPost(AckMbox, (void *)1); /*发送接收到数据的应答消息*/ } }
运行结果:
3)使用消息队列
#define TASK_STK_SIZE 512 #define TASK_START_ID 0 #define TASK_CLK_ID 1 #define TASK_1_ID 2 #define TASK_2_ID 3 #define TASK_3_ID 4 #define TASK_4_ID 5 #define TASK_5_ID 6 #define TASK_START_PRIO 10 #define TASK_CLK_PRIO 11 #define TASK_1_PRIO 12 #define TASK_2_PRIO 13 #define TASK_3_PRIO 14 #define TASK_4_PRIO 15 #define TASK_5_PRIO 16 #define MSG_QUEUE_SIZE 20 /* 消息队列大小*/ typedef struct { char TaskName[30]; INT16U TaskCtr; INT16U TaskExecTime; INT32U TaskTotExecTime; } TASK_USER_DATA; OS_STK TaskStartStk[TASK_STK_SIZE]; OS_STK TaskClkStk[TASK_STK_SIZE]; OS_STK Task1Stk[TASK_STK_SIZE]; OS_STK Task2Stk[TASK_STK_SIZE]; OS_STK Task3Stk[TASK_STK_SIZE]; OS_STK Task4Stk[TASK_STK_SIZE]; OS_STK Task5Stk[TASK_STK_SIZE]; TASK_USER_DATA TaskUserData[7]; OS_EVENT *MsgQueue; /*消息队列指针*/ void *MsgQueueTbl[20]; /*消息存储*/ void main (void) { PC_DispClrScr(DISP_BGND_BLACK); OSInit(); PC_DOSSaveReturn(); PC_VectSet(uCOS, OSCtxSw); PC_ElapsedInit(); strcpy(TaskUserData[TASK_START_ID].TaskName, "StartTask"); OSTaskCreateExt(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], TASK_START_PRIO, TASK_START_ID, &TaskStartStk[0], TASK_STK_SIZE, &TaskUserData[TASK_START_ID], 0); OSStart(); } void TaskStart (void *pdata) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif INT16S key; pdata = pdata; TaskStartDispInit(); OS_ENTER_CRITICAL(); PC_VectSet(0x08, OSTickISR); PC_SetTickRate(OS_TICKS_PER_SEC); OS_EXIT_CRITICAL(); OSStatInit(); MsgQueue = OSQCreate(&MsgQueueTbl[0], MSG_QUEUE_SIZE); /*创建消息队列,大小为*/ TaskStartCreateTasks(); for (;;) { TaskStartDisp(); if (PC_GetKey(&key)) { if (key == 0x1B) { PC_DOSReturn(); } } OSCtxSwCtr = 0; OSTimeDly(OS_TICKS_PER_SEC); } } void Task1 (void *pdata) { char *msg; INT8U err; pdata = pdata; for (;;) { msg = (char *)OSQPend(MsgQueue, 0, &err);//从消息队列中取消息 PC_DispStr(70, 13, msg, DISP_FGND_YELLOW + DISP_BGND_BLUE); OSTimeDlyHMSM(0, 0, 0, 100); } } void Task2 (void *pdata) { char msg[20]; pdata = pdata; strcpy(&msg[0], "Task 2"); for (;;) { OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500); } } void Task3 (void *pdata) { char msg[20]; pdata = pdata; strcpy(&msg[0], "Task 3"); for (;;) { OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500); } } void Task4 (void *pdata) { char msg[20]; pdata = pdata; strcpy(&msg[0], "Task 4"); for (;;) { OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500); } } void OSTaskStatHook (void) { char s[80]; INT8U i; INT32U total; INT8U pct; total = 0L; /* Totalize TOT. EXEC. TIME for each task for (i = 0; i < 7; i++) { total += TaskUserData[i].TaskTotExecTime; DispTaskStat(i); /* Display task data } if (total > 0) { for (i = 0; i < 7; i++) { /* Derive percentage of each task */ pct = 100 * TaskUserData[i].TaskTotExecTime / total; sprintf(s, "%3d %%", pct); PC_DispStr(62, i + 11, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY); } } if (total > 1000000000L) { /* Reset total time counters at 1 billion for (i = 0; i < 7; i++) { TaskUserData[i].TaskTotExecTime = 0L; } } } void OSTaskSwHook (void) { INT16U time; TASK_USER_DATA *puser; time = PC_ElapsedStop(); /* This task is done PC_ElapsedStart(); /* Start for next task puser = OSTCBCur->OSTCBExtPtr; /* Point to used data if (puser != (TASK_USER_DATA *)0) { puser->TaskCtr++; /* Increment task counter puser->TaskExecTime = time; /* Update the task's execution time puser->TaskTotExecTime += time; /* Update the task's total execution time } }
运行结果: