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