博客專欄

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

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

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

簡介:

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

知識(shí)點(diǎn):

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

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

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

消息隊(duì)列的使用場合

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

發(fā)送消息

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

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

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

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

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

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

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

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

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

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

例子說明:

下面例子是通過onenet 平臺(tái)發(fā)送不定長命令,在開發(fā)板的命令響應(yīng)回掉函數(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ù)復(fù)制到靜態(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ā)送消息到消息隊(duì)列中 */
            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)
    {

                      /* 從消息隊(duì)列中接收消息 */

                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)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請聯(lián)系工作人員刪除。



關(guān)鍵詞:

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉