如果把郵箱比作訊號量的公升級版,那訊息佇列就是郵箱的公升級版,郵箱可以實現從乙個任務向另乙個任務傳送乙個指標變數,訊息佇列則可以實現從乙個任務向
另乙個任務傳送多個指標變數,而且每個指標指向的資料結構變數也可以有不同。
使用訊息佇列需要注意的恩地方是:乙個任務或者中斷服務子程式可以呼叫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...