今天,作了uc/OS-II系統的消息循環的實驗,寫一些收穫。編程
先說說消息機制的原理。經過消息循環能夠實現基於時間驅動的應用程序,即每個事件都會產生特定的消息,而後這個消息被髮送到某個/某些任務消息隊列中,任務讀取到消息後做出相應的處理。任務消息隊列通常採用FIFO結構,即最早發送的消息任務會最早讀取到。
windows
用uc/OS實現的系統消息循環感受相似windows編程的消息機制。系統不斷輪詢來從消息隊列中取出最近的消息進行處理。固然,用uc/OS實現的消息機制就要比windows的簡單多了。在uc/OS中,通訊機制裏面有一種就是消息隊列,經過這種通訊方式咱們就能在uc/OS中實現咱們的消息機制。數組
在uc/OS中,消息隊列能夠工做與一對一的工做方式,即一個任務發送消息到消息隊列,而另外一個任務從消息隊列中讀取消息。這種方式簡單也經常使用。另外還有一種多對一的工做方式,即多個任務發送消息隊列到同一個消息隊列,而另外只有一個任務從這個消息隊列中讀取信息,這種便是咱們實現消息機制須要用到的工做方式。固然,消息隊列還有其餘工做方式,可是都不經常使用。函數
咱們把消息隊列做爲任務消息隊列,而後任務就能夠經過讀取消息隊列中的消息來獲取消息。固然,通常哪一個任務須要處理消息循環纔會創建相應本身的任務消息隊列。消息的儲存須要空間,因此還須要定義一個數組來進行消息的儲存。由於消息的類型不一樣,因此數組的類型爲void。而將任務隊列與任務消息隊列存儲區鏈接起來的關鍵就是OS_EVENT *OSQCreate (void **start, INT16U size)消息隊列建立函數。任務消息的隊列建立需在啓動uc/OS以前。ui
實驗中用到的關於消息函數已經有現成的了。在任務消息頭文件中,咱們能夠自定義消息。spa
如:指針
#define TM_KEY 5762隊列
#define TM_KEYDOWN 5763事件
......get
定義好消息結構體
typedef struct tagMSG
{
uint32 message; // 消息值
uint32 wParam; // 消息附加信息1
uint32 lParam; // 消息附加信息2
} MSG;
而後是最重要的兩個消息函數SendMessage()和GetMessage()。
/****************************************************************************
* 名稱:SendMessage()
* 功能:發送一個消息,即消息發送管理器。
* 根據實際狀況,將消息分派到不一樣的任務消息隊列中。
* 入口參數:msg 所要發送的消息(指針)
* 出口參數:操做成功返回TRUE,不然返回FALSE。
****************************************************************************/
uint8 SendMessage(MSG *msg)
{
uint32 message;
TMQ *target;
uint8 err;
message = msg->message;
switch(message)
{
case TM_KEY:
case TM_KEYDOWN:
case TM_KEYUP:
target = task_tmq; // 如果鍵盤消息,向task1_tmq任務消息隊列發送
break;
case TM_UART0RCV:
target = task_tmq; // 如果串口接收消息,向task1_tmq任務消息隊列發送
break;
// (在此添加用戶任務消息分派處理)
default: target = NULL;
break;
}
err = OSQPost(target, msg);
if(err==OS_NO_ERR)
return(TRUE);
else
return(FALSE);
}
/****************************************************************************
* 名稱:GetMessage()
* 功能:等待一個消息。當接收到消息時才返回。
* 入口參數:tmq 等待的任務消息隊列(指針)
* 出口參數:返回接收到的消息。
****************************************************************************/
MSG *GetMessage(TMQ *tmq)
{
uint8 err;
return(OSQPend(tmq, 0, &err));
}
具體實現的代碼就不用寫了,重要是這個思想和實現方法。