1. 程式人生 > >UCOS訊息佇列的使用【轉+原創】

UCOS訊息佇列的使用【轉+原創】

 

訊息佇列的使用
    1、 需在以下檔案中配置如下內容
        OS_CFG.H
        OS_MAX_QS      N     你需要的值
        根據需要自己配置
 #define OS_Q_EN                   1    /* Enable (1) or Disable (0) code generation for QUEUES         */
 #define OS_Q_ACCEPT_EN            1    /*     Include code for OSQAccept()                             */
 #define OS_Q_DEL_EN               1    /*     Include code for OSQDel()                                */
 #define OS_Q_FLUSH_EN             1    /*     Include code for OSQFlush()                              */
 #define OS_Q_POST_EN              1    /*     Include code for OSQPost()                               */
 #define OS_Q_POST_FRONT_EN        1    /*     Include code for OSQPostFront()                          */
 #define OS_Q_POST_OPT_EN          1    /*     Include code for OSQPostOpt()                            */
 #define OS_Q_QUERY_EN             1    /*     Include code for OSQQuery()                              */


    2、 建立一個指向訊息陣列的指標和陣列的大小,該指標陣列必須申明為void型別,如下:
        void    *MyArrayOfMsg[SIZE];


    3、 宣告一個OS_EVENT型別的指標指向生成的佇列,如下:
        OS_EVENT  *QSem;


    4、 呼叫OSQcreate()函式建立訊息佇列,如下:
 QSem      =  OSQcreate(&MyArrayOfMsg[0],SIZE);


    5、 等待訊息佇列中的訊息,OSQPend()。

void  *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err):
 必須保證訊息佇列已經被建立。
 timeout定義的是等待超時時間,如果為0則表示無期限的等待
 err表示的是在等待訊息隊列出錯時的返回型別,有以下幾種:
 OS_ERR_PEVENT_NULL     //訊息佇列不存在
 OS_ERR_EVENT_TYPE
 OS_TIMEOUT  //訊息佇列等待超時
 OS_NO_ERR              //訊息佇列接收到訊息

 獲得訊息佇列示例
 type    *GETQ;
 INT8U   err;
 GETQ    =  (type *)OSQPend(QSem, time, &err);
 if(err  ==  OS_NO_ERR){
  無錯處理
 }
 else{
  出錯處理
 }
 

6.1 向訊息佇列傳送一則訊息(FIFO),OSQPost();  INT8U  OSQPost (OS_EVENT *pevent, void *msg):
 函式返回值有:
 OS_ERR_PEVENT_NULL
 OS_ERR_POST_NULL_PTR
 OS_ERR_EVENT_TYPE
 OS_Q_FULL
 OS_NO_ERR
 引數:pevent,*msg
    6.2 向訊息佇列傳送一則訊息(LIFO) INT8U  OSQPostFront (OS_EVENT *pevent, void *msg)
    6.3 向訊息佇列傳送一則訊息(LIFO或者FIFO) INT8U  OSQPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
 引數: opt
  如果經opt引數中的OS_POST_OPT_BROADCAST位置為1,則所有正在等待訊息的任務都能接收到這則訊息,並且被OS_EventTaskRdy()從等待列表中刪除
  如果不是廣播方式,則只有等待訊息的任務中優先順序最高的任務能夠進入就緒態。然後,OS_EventTaskRdy()從等待列表中把等待訊息的任務中優先順序最高的任務刪除。
 注: 如果此函式由ISR呼叫,則不會發生任務切換,直到中斷巢狀的最外層中斷服務子程式呼叫OSIntExit()函式時,才能進行任務切換


    7、 無等待的從訊息佇列中獲得訊息,OSQAccept(); void  *OSQAccept (OS_EVENT *pevent, INT8U *err)
 err可能的返回值:
 OS_ERR_PEVENT_NULL
 OS_Q_EMPTY
 OS_NO_ERR
 函式的返回值:訊息,0


    8、 清空訊息佇列 INT8U  OSQFlush (OS_EVENT *pevent)
 函式返回值:
 OS_ERR_PEVENT_NULL
 OS_ERR_EVENT_TYPE
 OS_NO_ERR


    9、 獲取訊息佇列的狀態,OSQQuery(); INT8U  OSQQuery (OS_EVENT *pevent, OS_Q_DATA *p_q_data)
 函式返回值:
 OS_ERR_PEVENT_NULL
 OS_ERR_EVENT_TYPE
 OS_NO_ERR
 OS_Q_DATA資料結構在ucos_ii.h中

==================================華麗的分割線===================================

現在來說一下這個訊息佇列所傳遞的資料型別和特性。

首先,這個訊息佇列不是真正意義上的“佇列”,它呢只會把每次存入的資料指標排隊,而不會儲存該資料。所以呼叫OSQPost時如果每次都是相同的指標,那就說明 白放了,因為讀取的時候讀到的是同一個指標,他總是最新的資料,老的沒了,何來佇列?

其次,該佇列可以儲存void*型別指標,即所有資料型別都適用,管他是整型還是結構體。

現在這個佇列不是真佇列,那怎麼解決?莫急,看下面:

我這裡提一種簡單的方法,複雜的各位資格解決吧。

1、定義一個存放資料的緩衝區陣列,這樣每次向對列新增時就可以用不同的地址。例如struct my_struct data_array[10]

2、然後就是怎麼變這個陣列下標的問題,直接定義一個變數來尋找,然後使用++,到最後再折回來就好了,例如:

int idx=0;

idx++;

idx %= BUF_SIZE;

3、對於速度能及時解決的任務,那下標這樣搞就可以,如果不行,那可能要重新考慮覆蓋的問題了。