ucos訊息佇列

2021-07-25 21:03:46 字數 3809 閱讀 9157

如果把郵箱比作訊號量的公升級版,那訊息佇列就是郵箱的公升級版,郵箱可以實現從乙個任務向另乙個任務傳送乙個指標變數,訊息佇列則可以實現從乙個任務向

另乙個任務傳送多個指標變數,而且每個指標指向的資料結構變數也可以有不同。

使用訊息佇列需要注意的恩地方是:乙個任務或者中斷服務子程式可以呼叫osqpost(),osqpostfront(),osqflush(),或者osqaccept函式,但是只有任務

可以呼叫osqpend()和osqqquery函式。

我們知道,每個事件有乙個對應事件控制塊,用於記錄有關這個事件的訊息,訊息佇列也不理瓦,乙個訊息佇列對應乙個佇列控制塊。

相對而言,郵箱而言,ucosii定義了乙個資料結構來儲存訊息佇列的資訊,

typedef struct os_qos_q;

osqptr在空閒佇列控制塊中鏈結所有的佇列控制塊,一旦建立了訊息佇列,該域就不再有用了

osqstart是指向訊息佇列的指標陣列的起始位址的指標,使用者應用程式在使用訊息佇列之前必須先定義該陣列。

osqin 是指向訊息佇列中插入下一條訊息的位置的指標,當osqin和osqend相等時,osqin被調整指向訊息佇列的起始單元。

osqout是指向訊息佇列中下乙個取出訊息的位置的指標,當osqout和osqend相等時,osqout被調整指向訊息佇列的起始單元。

osqsize是訊息佇列中總的單元數,該值是在建立訊息佇列時由使用者應用程式決定的,該值最大可以是65535

osqentries是訊息佇列中當前的訊息數量,當訊息佇列是空的時,該值為0,當訊息佇列滿了以後,改制和osqsize值一樣,在訊息uil剛建立時,該值為0.

ucosii提供了7個訊息佇列進行操作的函式

1.建立乙個訊息佇列,osqcreat();

2.等待乙個訊息佇列中的訊息 osqpend();

3.向訊息佇列傳送乙個訊息(fifo)osqpost();

4.向訊息佇列傳送乙個訊息(後進先出fifo),osqpostfront();

5.無等待地從乙個訊息佇列中取得訊息osqaccept()

6.清空乙個訊息佇列osqflush();

7.查詢乙個訊息佇列的狀態osqquery();

訊息佇列最根本的部分時乙個緩衝區,其中的每個單元包含乙個指標,佇列未滿時,osqin指向下乙個存放訊息的位址單元,如果佇列已滿,osqin則與osqout指向同一單元,如果在osqin指向的單元插入新的訊息的指標,就構成fifo佇列,相反,如果在osqout指向的單元的下乙個單元插入新的指標,就構成lifo佇列。當osqentries和osqsize相等,說明佇列已滿,訊息指標總是從osqout指向的單元取出,指標osqstart和osqend定義了訊息指標陣列的頭尾,以便在osqin和osqout到達佇列的邊緣時,進行編輯檢查和必要的調整,實現迴圈功能。

訊息佇列通常可以應用一下兩個地方:

1.儲存外部事件:外部事件由中斷收集,然後儲存到佇列中。

2.串列埠接收程式中的接收緩衝區,可以理解為訊息佇列。

使用乙個訊息佇列的步驟如下:

1.建立乙個指向訊息陣列的指標和陣列的大小,該指標陣列必須為void型別

void *myarrayofmsg[size];

2.宣告乙個os_event 型別的指標指向生成的佇列

os_event *qsem;

3.呼叫osqcreate()函式建立訊息佇列,如下:

qsem =osqcreate(&myarrayofmsg[0],size);

4.等待訊息佇列中的訊息,osqpend();

5.向訊息佇列傳送一則訊息。

建立乙個訊息佇列,osqcreate()的實現**如下:

os_event *osqcreate(void **start,int16u size)

os_eixt_critical();

if(pevent!=(os_event*)0)

os_exit_critical();

if(pq!=(os_q*)0)

else

} return(pevent);              (9) }

它和建立郵箱,建立訊號量過程很相似,首先申請控制塊,接著初始化這個控制塊,和建立郵箱,訊號量不同,建立訊息佇列過程

是多申請乙個佇列控制塊

osqcreate()首先從空閒事件控制塊鍊錶中取得乙個事件控制塊(1);並對剩餘的空閒事件控制塊列表的指標做相應的調整,

使它執行下乙個空閒事件控制塊(2),接著osqcreate()函式從空閒佇列控制塊列表中取出乙個佇列控制塊(3),如果空閒佇列控制塊是可以

就對其進行初始(4).然後該函式將事件控制塊的型別設定為os_event_type_q(5),使其oseventptr指標指向佇列控制塊(6),osqcreate還要呼叫oseventwaitlistinit()

向它的呼叫函式返回乙個指向事件控制塊的指標(9),該指標將在呼叫osqpend(),osqpost(),osqpostfront(),osqflush(),osqaccept和osqquery

等訊息佇列處理函式的使用,因此,該指標可以被看作是對訊息佇列的控制代碼,值得注意的是,如果此時沒有空閒的事件控制塊,osqcreate函式將返回乙個null指標,如果沒有

佇列控制塊可以使用,為了不浪費事件控制塊資源,osqcreate函式將把剛剛取得的事件控制塊反給空閒控制塊列表。

#define task_stk_size    512

#define n_messages      128

os_stk   starttaskstk[task_stk_size]

os_stk   mytaskstk[task_stk_size]

os_stk   youtaskstk[task_stk_size];

char *s_flag;  //該字串指示哪個任務在執行

char *ss;  //存放接收到的訊息指標

char *s100;//存放傳送訊息的指標

char *s;

char *s500;

void *msggrp[n_messages];//定義訊息指標陣列

//創訊息佇列,首先需要定義乙個指標陣列,然後把各個訊息資料緩衝區的首位址存入這個陣列中,最後呼叫函式osqcreate()來建立訊息佇列

int8u err;

int8u y=0;

os_event *str_q; //定義事件控制塊指標 佇列的事件控制塊指標,用於存放建立訊息佇列的指標

void mytask(void *data)

void starttask(void *data);

void youtask(void *data);

void  main(void)

void starttask(void *pdata)

if(ostimeget()>1000&&ostimeget()<1500)

if(pc_getkey(&key)==true)

} ostimedlyhmsm(0,0,1,0); }

} void mytask(void *pdata)

} 執行的現象說明上面分析時正確的,因為當時鐘節拍大於100,小於500時,會傳送第乙個if語句中的兩個字串

s100和s

下面執行的任務接收到並且顯示,當時鐘節拍數大於1000小於1500時,傳送第二個if語句的字元,下面執行的、人

//接收並顯示,當時鐘節拍數大於1500時,就不再傳送訊息,下面的任務得不到就無限等待下去,所以就不再顯示

從執行的現象不難可以看出,有時mytask或youtask執行了,但是沒有得到訊息而處於等待狀態,使用上面的

方法很清純地看出來任務排程和執行的關係,mytask和youtask是交執行的,因為延時時間相等

ucos 訊息佇列

1 訊息佇列 訊息佇列可以同時傳遞多個訊息,當時間控制塊中的變數oseventtype值為 os event type q表示此事件控制塊是用來表示訊息佇列的。訊息佇列資料結構如下 在上面的事件控制塊的oseventptr指標指向了訊息佇列結構體 os q。改結構體os q管理者乙個訊息陣列,這個陣...

uC OS 的訊息佇列 uC OS學習筆記(七)

1.訊息佇列的介紹 使用訊息佇列可在任務之間傳遞多條訊息。訊息佇列相當於訊息郵箱集合,乙個郵箱只能在任務間傳遞一條訊息,而訊息佇列則可以傳遞多條訊息。訊息佇列由三部分組成 事件控制塊 訊息佇列和訊息。2.訊息佇列的操作 a 建立訊息佇列 qsqcreate void start,int16u siz...

ucos訊號量訊息佇列

全域性變數 static int msg int os q data msg 訊息佇列主任務 void start task void p arg led任務0 void led0 task void p arg if err os err none ostimedlyhmsm 0,0,3,0,os...