博客專欄

EEPW首頁 > 博客 > 【RT-Thread 筆記】----使用消息隊列發(fā)送不定長數(shù)據(jù)

【RT-Thread 筆記】----使用消息隊列發(fā)送不定長數(shù)據(jù)

發(fā)布人:電子禪石 時間:2019-02-13 來源:工程師 發(fā)布文章

簡介:

本文簡要介紹如何使用RT-Thread 的消息隊列 發(fā)送不定長數(shù)據(jù)的使用。數(shù)據(jù)比較經(jīng)典的用法,可以在很多數(shù)據(jù)傳輸?shù)膱龊蠎谩?/p>

知識點:

1.參考內(nèi)容:

https://www.rt-thread.org/document/site/programming-manual/ipc2/ipc2/#_2

2.要點摘錄:通過定義結構體:數(shù)據(jù)塊首地址和數(shù)據(jù)塊大小 來進行數(shù)據(jù)的傳遞。非常通用。

消息隊列的使用場合

消息隊列可以應用于發(fā)送不定長消息的場合,包括線程與線程間的消息交換,以及中斷服務例程中給線程發(fā)送消息(中斷服務例程不能接收消息)。下面分發(fā)送消息和同步消息兩部分來介紹消息隊列的使用。

發(fā)送消息

消息隊列和郵箱的明顯不同是消息的長度并不限定在 4 個字節(jié)以內(nèi);另外,消息隊列也包括了一個發(fā)送緊急消息的函數(shù)接口。但是當創(chuàng)建的是一個所有消息的最大長度是 4 字節(jié)的消息隊列時,消息隊列對象將蛻化成郵箱。這個不限定長度的消息,也及時的反應到了代碼編寫的場合上,同樣是類似郵箱的代碼:

struct msg{
    rt_uint8_t *data_ptr;    /* 數(shù)據(jù)塊首地址 */
    rt_uint32_t data_size;   /* 數(shù)據(jù)塊大小   */};

和郵箱例子相同的消息結構定義,假設依然需要發(fā)送這樣一個消息給接收線程。在郵箱例子中,這個結構只能夠發(fā)送指向這個結構的指針(在函數(shù)指針被發(fā)送過去后,接收線程能夠正確的訪問指向這個地址的內(nèi)容,通常這塊數(shù)據(jù)需要留給接收線程來釋放)。而使用消息隊列的方式則大不相同:

void send_op(void *data, rt_size_t length){    struct msg msg_ptr;

    msg_ptr.data_ptr = data;  /* 指向相應的數(shù)據(jù)塊地址 */
    msg_ptr.data_size = length; /* 數(shù)據(jù)塊的長度 */

    /* 發(fā)送這個消息指針給 mq 消息隊列 */
    rt_mq_send(mq, (void*)&msg_ptr, sizeof(struct msg));
}

注意,上面的代碼中,是把一個局部變量的數(shù)據(jù)內(nèi)容發(fā)送到了消息隊列中。在接收線程中,同樣也采用局部變量進行消息接收的結構體:

void message_handler(){    struct msg msg_ptr; /* 用于放置消息的局部變量 */

    /* 從消息隊列中接收消息到 msg_ptr 中 */
    if (rt_mq_recv(mq, (void*)&msg_ptr, sizeof(struct msg)) == RT_EOK)
    {        /* 成功接收到消息,進行相應的數(shù)據(jù)處理 */
    }
}

因為消息隊列是直接的數(shù)據(jù)內(nèi)容復制,所以在上面的例子中,都采用了局部變量的方式保存消息結構體,這樣也就免去動態(tài)內(nèi)存分配的煩惱了(也就不用擔心,接收線程在接收到消息時,消息內(nèi)存空間已經(jīng)被釋放)。

例子說明:

下面例子是通過onenet 平臺發(fā)送不定長命令,在開發(fā)板的命令響應回掉函數(shù)中 將數(shù)據(jù)發(fā)送到打印線程:

/* onenet mqtt command response callback function */
static void onenet_cmd_rsp_cb(uint8_t *recv_data, size_t recv_size, uint8_t **resp_data, size_t *resp_size)
{
    char res_buf[] = { "cmd is received!\n" };

    log_d("recv data is %.*s\n", recv_size, recv_data);
    rs485_transport(recv_data,recv_size);
    /* user have to malloc memory for response data */
    *resp_data = (uint8_t *) ONENET_MALLOC(strlen(res_buf));

    strncpy(*resp_data, res_buf, strlen(res_buf));

    *resp_size = strlen(res_buf);
        
}
static rt_uint8_t temp_data[20];
void rs485_transport(uint8_t *recv_data, size_t recv_size)
{
          int result;
                struct msg msg_ptr;
             //增加一句 先  把數(shù)據(jù)復制到靜態(tài)變量中。
               strncpy(temp_data, recv_data, recv_size);
                msg_ptr.data_ptr = temp_data;//recv_data;
                msg_ptr.data_size = recv_size;
    rt_pin_write(RS485_RE_DE_Pin, PIN_HIGH);
/* 發(fā)送消息到消息隊列中 */
            result = rt_mq_send(&mq,(void*)&msg_ptr,sizeof(struct msg));
            if (result != RT_EOK)
            {
                rt_kprintf("rt_mq_send ERR\n");
            }

            rt_kprintf("thread onenet: send message - %s\n", msg_ptr.data_ptr);
    //rt_pin_write(RS485_RE_DE_Pin, PIN_LOW);
}

接收處理:
static void serial_thread_entry(void *parameter)
{
    char buf;
    rt_uint8_t k;
        struct msg msg_prt;
    while (1)
    {

                      /* 從消息隊列中接收消息 */

                if (rt_mq_recv(&mq, (void*)&msg_prt, sizeof(struct msg), RT_WAITING_FOREVER) == RT_EOK)
        {
        
                        rt_device_write(serial, 0, (void*)msg_prt.data_ptr, msg_prt.data_size);
        }
    
    }
}

*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權請聯(lián)系工作人員刪除。



關鍵詞:

相關推薦

技術專區(qū)

關閉