新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > μC/OS-II的任務之間的通訊與同步

μC/OS-II的任務之間的通訊與同步

作者: 時間:2016-10-08 來源:網絡 收藏

程序清單L6.26清空消息隊列

INT8UOSQFlush(OS_EVENT*pevent)

{

OS_Q*pq;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_Q){(1)

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

pq=pevent->OSEventPtr;

pq->OSQIn=pq->OSQStart;(2)

pq->OSQOut=pq->OSQStart;

pq->OSQEntries=0;

OS_EXIT_CRITICAL();

return(OS_NO_ERR);

}

6.8.7 查詢一個消息隊列的狀態(tài),OSQQuery()

OSQQuery()函數使用戶可以查詢一個消息隊列的當前狀態(tài)。 程序清單L6.27是該函數的源代碼。OSQQuery()需要兩個參數:一個是指向消息隊列的指針pevent。它是在建立一個消息隊列時,由OSQCreate()函數返回的;另一個是指向OS_Q_DATA(見uCOS_II.H)數據結構的指針pdata。該結構包含了有關消息隊列的信息。在調用OSQQuery()函數之前,必須先定義該數據結構變量。OS_Q_DATA結構包含下面的幾個域:

.OSMsg 如果消息隊列中有消息,它包含指針.OSQOut所指向的隊列單元中的內容。如果隊列是空的,.OSMsg包含一個NULL指針。

.OSNMsgs是消息隊列中的消息數(.OSQEntries的拷貝)。

.OSQSize 是消息隊列的總的容量

.OSEventTbl[]和.OSEventGrp是消息隊列的等待任務列表。通過它們,OSQQuery()的調用函數可以得到等待該消息隊列中的消息的任務總數。

OSQQuery()函數首先檢查pevent指針指向的事件控制塊是一個消息隊列[L6.27(1)],然后復制等待任務列表[L6.27(2)]。如果消息隊列中有消息[L6.27(3)],.OSQOut指向的隊列單元中的內容被復制到OS_Q_DATA結構中[L6.27(4)], 否則的話, 就復制一個NULL指針[L6.27(5)]。

最后,復制消息隊列中的消息數和消息隊列的容量大小[L6.27(6)]。

程序清單L6.27程序消息隊列的狀態(tài)

INT8UOSQQuery(OS_EVENT*pevent,OS_Q_DATA*pdata)

{

OS_Q*pq;

INT8Ui;

INT8U*psrc;

INT8U*pdest;

OS_ENTER_CRITICAL();

if(pevent->OSEventType!=OS_EVENT_TYPE_Q){(1)

OS_EXIT_CRITICAL();

return(OS_ERR_EVENT_TYPE);

}

pdata->OSEventGrp=pevent->OSEventGrp;(2)

psrc=pevent->OSEventTbl[0];

pdest=pdata->OSEventTbl[0];

for(i=0;i

*pdest++=*psrc++;

}

pq=(OS_Q*)pevent->OSEventPtr;

if(pq->OSQEntries>0){(3)

pdata->OSMsg=pq->OSQOut;(4)

}else{

pdata->OSMsg=(void*)0;(5)

}

pdata->OSNMsgs=pq->OSQEntries;(6)

pdata->OSQSize=pq->OSQSize;

OS_EXIT_CRITICAL();

return(OS_NO_ERR);

}

6.8.8 使用消息隊列讀取模擬量的值

在控制系統(tǒng)中,經常要頻繁地讀取模擬量的值。這時,可以先建立一個定時任務OSTimeDly()[見5.00節(jié),延時一個任務,OSTimeDly()],并且給出希望的抽樣周期。然后,如圖F6.11所示,讓A/D采樣的任務從一個消息隊列中等待消息。該程序最長的等待時間就是抽樣周期。當沒有其它任務向該消息隊列中發(fā)送消息時,A/D采樣任務因為等待超時而退出等待狀態(tài)并進行執(zhí)行。這就模仿了OSTimeDly()函數的功能。

也許,讀者會提出疑問,既然OSTimeDly()函數能完成這項工作,為什么還要使用消息隊列呢?這是因為,借助消息隊列,我們可以讓其它的任務向消息隊列發(fā)送消息來終止A/D采樣任務等待消息,使其馬上執(zhí)行一次A/D采樣。此外,我們還可以通過消息隊列來通知A/D采樣程序具體對哪個通道進行采樣,告訴它增加采樣頻率等等,從而使得我們的應用更智能化。換句話說,我們可以告訴A/D采樣程序,“現在馬上讀取通道3的輸入值!”之后,該采樣任務將重新開始在消息隊列中等待消息,準備開始一次新的掃描過程。

圖F6.11讀模擬量輸入——Figure6.11

6.8.9 使用一個消息隊列作為計數信號量

在消息隊列初始化時,可以將消息隊列中的多個指針設為非NULL值(如void*1),來實現計數信號量的功能。這里,初始化為非NULL值的指針數就是可用的資源數。系統(tǒng)中的任務可以通過OSQPend()來請求“信號量”,然后通過調用OSQPost()來釋放“信號量”,如程序清單L6.28。如果系統(tǒng)中只使用了計數信號量和消息隊列,使用這種方法可以有效地節(jié)省代碼空間。

這時將OS_SEM_EN設為0,就可以不使用信號量,而只使用消息隊列。值得注意的是,這種方法

為共享資源引入了大量的指針變量。也就是說,為了節(jié)省代碼空間,犧牲了RAM空間。另外,

對消息隊列的操作要比對信號量的操作慢,因此,當用計數信號量同步的信號量很多時,這種

方法的效率是非常低的。

程序清單L6.28使用消息隊列作為一個計數信號量

OS_EVENT*QSem;

void*QMsgTbl[N_RESOURCES]

voidmain(void)

{

OSInit();

.

QSem=OSQCreate(QMsgTbl[0],N_RESOURCES);

for(i=0;i

OSQPost(Qsem,(void*)1);

}

.

.

OSTaskCreate(Task1,..,..,..);

.

.

OSStart();

}

voidTask1(void*pdata)

{

INT8Uerr;

for(;;){

OSQPend(QSem,0,err);/*得到對資源的訪問權*/

.

./*任務獲得信號量,對資源進行訪問*/

.

OSMQPost(QSem,(void*)1);/*釋放對資源的訪問權*/

}

}


上一頁 1 2 3 4 5 6 7 8 9 10 11 下一頁

關鍵詞:

評論


相關推薦

技術專區(qū)

關閉