* 內容簡述:
本例程操作系統采用ucos2.86a版本, 建立了5個任務
任務名 優(yōu)先級
APP_TASK_START_PRIO 2 主任務
Task_Com1_PRIO 4 COM1通信任務
Task_Led1_PRIO 7 LED1 閃爍任務
Task_Led2_PRIO 8 LED2 閃爍任務
Task_Led3_PRIO 9 LED3 閃爍任務
當然還包含了系統任務:
OS_TaskIdle 空閑任務-----------------優(yōu)先級最低
OS_TaskStat 統計運行時間的任務-------優(yōu)先級次低
1、主任務建立:
1 //建立主任務, 優(yōu)先級最高 建立這個任務另外一個用途是為了以后使用統計任務
2 os_err = OSTaskCreate((void (*) (void *)) App_TaskStart, //指向任務代碼的指針
3 (void *) 0, //任務開始執(zhí)行時,傳遞給任務的參數的指針
4 (OS_STK *) &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1], //分配給任務的堆棧的棧頂指針 從頂向下遞減
5 (INT8U) APP_TASK_START_PRIO); //分配給任務的優(yōu)先級
這個采用老版本的任務建立函數,第一個參數通俗的說法就是該任務對應的函數,如下:
1 static void App_TaskStart(void* p_arg)
2 {
3 (void) p_arg;
4 //初始化ucos時鐘節(jié)拍
5 OS_CPU_SysTickInit(); /* Initialize the SysTick. */
6
7 //使能ucos 的統計任務
8 #if (OS_TASK_STAT_EN > 0)
9 //----統計任務初始化函數
10 OSStatInit(); /* Determine CPU capacity. */
11 #endif
12 //建立其他的任務
13 App_TaskCreate();
14
15 while (1)
16 {
17 //1秒一次循環(huán)
18 OSTimeDlyHMSM(0, 0,1, 0);
19 }
20 }
當主任務建立之后,程序就轉到該函數處,調用 App_TaskCreate();建立其他任務,然后進入死循環(huán),我們會發(fā)現:這里的主任務在建立其他任務后就沒啥作用的,這時可以調用相應的函數將主任務給殺死,這里沒有這樣做,只是讓主任務進入循環(huán)。
2、其他任務建立:
1 static void App_TaskCreate(void)
2 {
3 //CPU_INT08U os_err;
4
5 //Com1_SEM=OSSemCreate(1); //建立串口1中斷的信號量
6 Com1_MBOX=OSMboxCreate((void *) 0); //建立串口1中斷的消息郵箱
7
8 //串口1接收及發(fā)送任務---------------------------------------------------------
9 OSTaskCreateExt(Task_Com1, //指向任務代碼的指針
10 (void *)0, //任務開始執(zhí)行時,傳遞給任務的參數的指針
11 (OS_STK *)&Task_Com1Stk[Task_Com1_STK_SIZE-1],//分配給任務的堆棧的棧頂指針 從頂向下遞減
12 Task_Com1_PRIO, //分配給任務的優(yōu)先級
13 Task_Com1_PRIO, //預備給以后版本的特殊標識符,在現行版本同任務優(yōu)先級
14 (OS_STK *)&Task_Com1Stk[0], //指向任務堆棧棧底的指針,用于堆棧的檢驗
15 Task_Com1_STK_SIZE, //指定堆棧的容量,用于堆棧的檢驗
16 (void *)0, //指向用戶附加的數據域的指針,用來擴展任務的任務控制塊
17 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //選項,指定是否允許堆棧檢驗,是否將堆棧清0,任務是否要進行浮點運算等等。
18 //LED1 閃爍任務------------------------------------------------------
19 OSTaskCreateExt(Task_Led1,(void *)0,(OS_STK *)&Task_Led1Stk[Task_Led1_STK_SIZE-1],Task_Led1_PRIO,Task_Led1_PRIO,(OS_STK *)&Task_Led1Stk[0],
20 Task_Led1_STK_SIZE,
21 (void *)0,
22 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);
23
24 //LED2 閃爍任務------------------------------------------------------
25 OSTaskCreateExt(Task_Led2,(void *)0,(OS_STK *)&Task_Led2Stk[Task_Led2_STK_SIZE-1],Task_Led2_PRIO,Task_Led2_PRIO,(OS_STK *)&Task_Led2Stk[0],
26 Task_Led2_STK_SIZE,
27 (void *)0,
28 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);
29
30 //LED3 閃爍任務------------------------------------------------------
31 OSTaskCreateExt(Task_Led3,(void *)0,(OS_STK *)&Task_Led3Stk[Task_Led3_STK_SIZE-1],Task_Led3_PRIO,Task_Led3_PRIO,(OS_STK *)&Task_Led3Stk[0],
32 Task_Led3_STK_SIZE,
33 (void *)0,
34 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);
35 }
這里是建立四個子任務第一個是串口通信的任務,一會再說,下面三個是LED閃爍任務,這里舉Task_Led1說明:
1 //LED1閃爍任務----------------------------------------
2 static void Task_Led1(void* p_arg)
3 {
4 (void) p_arg;
5 while (1)
6 {
7 LED_LED1_ON();
8 OSTimeDlyHMSM(0, 0, 0, milsec1);
9
10 LED_LED1_OFF();
11 OSTimeDlyHMSM(0, 0, 0, milsec1);
12 }
13 }
可見LED閃爍任務其實就是一個無限循環(huán),讓燈的電平每隔一定時間高、每隔一定時間低來呈現閃爍的效果。那么,他是怎樣實現任務切換的呢?這就是操作系統的功能了,操作系統根據每個任務的優(yōu)先級,在每個子任務執(zhí)行到一定時期查詢當前掛起任務的優(yōu)先級來選擇優(yōu)先級最高的進行