ucosII详解 下载本文

PC_DispChar(70, 16, '\\\\', DISP_FGND_WHITE + DISP_BGND_BLUE); OSTimeDly(20);

PC_DispChar(70, 16, '-', DISP_FGND_WHITE + DISP_BGND_BLUE); OSTimeDly(20);

PC_DispChar(70, 16, '/', DISP_FGND_WHITE + DISP_BGND_BLUE); OSTimeDly(20); } }

任务4(程序清单L1.16)向任务5发送消息并等待确认[程序清单L1.16(1)]。发送的消息是一个指向字符的指针。每当任务4从任务5收到确认[程序清单L1.16(2)],就将传递的ASCII码加1再发送[程序清单L1.16(3)],结果是不断的传送―ABCDEFG....‖。

程序清单 L 1.16 任务4 void Task4 (void *data) {

char txmsg; INT8U err;

data = data; txmsg = 'A'; for (;;) {

while (txmsg <= 'Z') {

OSMboxPost(TxMbox, (void *)&txmsg); (1) OSMboxPend(AckMbox, 0, &err); (2) txmsg++; (3) }

txmsg = 'A'; } }

当任务5 [程序清单L1.17]接收消息后[程序清单L1.17(1)](发送的字符),就将消息显示到屏幕上[程序清单L1.17(2)],然后延时1秒[程序清单L1.17(3)],再向任务4发送确认信息。

程序清单 L 1.17 任务5 void Task5 (void *data) {

char *rxmsg; INT8U err;

data = data; for (;;) {

rxmsg = (char *)OSMboxPend(TxMbox, 0, &err); (1) PC_DispChar(70, 18, *rxmsg, DISP_FGND_YELLOW+DISP_BGND_RED); (2) OSTimeDlyHMSM(0, 0, 1, 0); (3) OSMboxPost(AckMbox, (void *)1); (4) }

}

TaskClk()函数[程序清单L1.18]显示当前日期和时间,每秒更新一次。

程序清单 L 1.18 时钟显示任务 void TaskClk (void *data) {

Struct time now; Struct date today; char s[40];

data = data; for (;;) {

PC_GetDateTime(s);

PC_DispStr(0, 24, s, DISP_FGND_BLUE + DISP_BGND_CYAN); OSTimeDly(OS_TICKS_PER_SEC); } }

1.09例3

例3中使用了许多uCOS-II提供的附加功能。任务3使用了OSTaskCreateExt()中TCB的扩展数据结构,用户定义的任务切换对外接口函数(OSTaskSwHook()),用户定义的统计任务(statistic task )的对外接口函数(OSTaskStatHook())以及消息队列。例3的磁盘文件是\\SOFTWARE\%uCOS-II\\EX3_x86L,它包括9个任务。除了空闲任务(idle task)和统计任务(statistic task ),还有7个任务。与例1,例2一样,TaskStart()由main()函数建立,其功能是建立其他任务,并显示统计信息。 1.09.01 main()

main()函数[程序清单L1.19]和例2中的相不多,不同的是在用户定义的TCB扩展数据结构中可以保存每个任务的名称[程序清单L1.19(1)](扩展结构的声明在INCLUDES.H中定义,也可参看程序清单L1.20)。笔者定义了30个字节来存放任务名(包括空格)[程序清单L1.20(1)]。本例中没有用到堆栈检查操作,TaskStart()中禁止该操作[程序清单L1.19(2)]。

程序清单 L 1.19 例3的main()函数 void main (void) {

PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); OSInit();

PC_DOSSaveReturn();

PC_VectSet(uCOS, OSCtxSw); PC_ElapsedInit();

Strcpy(TaskUserData[TASK_START_ID].TaskName, \ (1) 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); (2) OSStart(); }

程序清单 L 1.20 TCB扩展数据结构。 typedef struct {

char TaskName[30]; (1) INT16U TaskCtr;

INT16U TaskExecTime; INT32U TaskTotExecTime; } TASK_USER_DATA;

1.09.02任务

TaskStart()的伪码如程序清单L1.21所示,与例2有3处不同: ? 为任务1,2,3建立了一个消息队列[程序清单L1.21(1)];

? 每个任务都有一个名字,保存在任务的TCB扩展数据结构中[程序清单L1.21(2)]; ? 禁止堆栈检查。

程序清单 L 1.21 TaskStart()的伪码。 void TaskStart (void *data) {

Prevent compiler warning by assigning ?data‘ to itself; Display a banner and non-changing text; Install uC/OS-II‘s tick handler; Change the tick rate to 200 Hz; Initialize the statistics task;

Create a message queue; (1) Create a task that will display the date and time on the screen;

Create 5 application tasks with a name stored in the TCB ext.; (2) for (;;) {

Display #tasks running; Display CPU usage in %;

Display #context switches per seconds; Clear the context switch counter; Display uC/OS-II‘s version; If (Key was pressed) {

if (Key pressed was the ESCAPE key) { Return to DOS; } }

Delay for 1 second; } }

任务1向消息队列发送一个消息[程序清单L1.22(1)],然后延时等待消息发送完成[程序清单L1.22(2)]。这段时间可以让接收消息的任务显示收到的消息。发送的消息有三种。 程序清单 L 1.22 任务1。 void Task1 (void *data) {

char one = '1';

char two = '2'; char three = '3';

data = data; for (;;) {

OSQPost(MsgQueue, (void *)&one); (1) OSTimeDlyHMSM(0, 0, 1, 0); (2) OSQPost(MsgQueue, (void *)&two); OSTimeDlyHMSM(0, 0, 0, 500);

OSQPost(MsgQueue, (void *)&three); OSTimeDlyHMSM(0, 0, 1, 0); } }

任务2处于等待消息的挂起状态,且不设定最大等待时间[程序清单L1.23(1)]。所以任务2将一直等待直到收到消息。当收到消息后,任务2显示消息并且延时500mS[程序清单L1.23(2)],延时的时间可以使任务3检查消息队列。 程序清单 L 1.23 任务2。 void Task2 (void *data) {

INT8U *msg; INT8U err;

data = data; for (;;) {

msg = (INT8U *)OSQPend(MsgQueue, 0, &err); (1) PC_DispChar(70, 14, *msg, DISP_FGND_YELLOW+DISP_BGND_BLUE); (2) OSTimeDlyHMSM(0, 0, 0, 500); (3) } }

任务3同样处于等待消息的挂起状态,但是它设定了等待结束时间250mS[程序清单L1.24(1)]。如果有消息来到,任务3将显示消息号[程序清单L1.24(3)],如果超过了等待时间,任务3就显示―T‖(意为timeout)[程序清单L1.24(2)]。

程序清单 L 1.24任务3

void Task3 (void *data) {

INT8U *msg; INT8U err;

data = data; for (;;) {

msg = (INT8U *)OSQPend(MsgQueue, OS_TICKS_PER_SEC/4, &err); (1) If (err == OS_TIMEOUT) {

PC_DispChar(70,15,'T',DISP_FGND_YELLOW+DISP_BGND_RED); (2) } else {

PC_DispChar(70,15,*msg,DISP_FGND_YELLOW+DISP_BGND_BLUE); (3)