【RT-Thread 筆記】----使用消息隊列發(fā)送不定長數(shù)據(jù)
簡介:
本文簡要介紹如何使用RT-Thread 的消息隊列 發(fā)送不定長數(shù)據(jù)的使用。數(shù)據(jù)比較經(jīng)典的用法,可以在很多數(shù)據(jù)傳輸?shù)膱龊蠎?yīng)用。
知識點:
1.參考內(nèi)容:
https://www.rt-thread.org/document/site/programming-manual/ipc2/ipc2/#_2
2.要點摘錄:通過定義結(jié)構(gòu)體:數(shù)據(jù)塊首地址和數(shù)據(jù)塊大小 來進行數(shù)據(jù)的傳遞。非常通用。
消息隊列的使用場合
消息隊列可以應(yīng)用于發(fā)送不定長消息的場合,包括線程與線程間的消息交換,以及中斷服務(wù)例程中給線程發(fā)送消息(中斷服務(wù)例程不能接收消息)。下面分發(fā)送消息和同步消息兩部分來介紹消息隊列的使用。
發(fā)送消息
消息隊列和郵箱的明顯不同是消息的長度并不限定在 4 個字節(jié)以內(nèi);另外,消息隊列也包括了一個發(fā)送緊急消息的函數(shù)接口。但是當(dāng)創(chuàng)建的是一個所有消息的最大長度是 4 字節(jié)的消息隊列時,消息隊列對象將蛻化成郵箱。這個不限定長度的消息,也及時的反應(yīng)到了代碼編寫的場合上,同樣是類似郵箱的代碼:
struct msg{
rt_uint8_t *data_ptr; /* 數(shù)據(jù)塊首地址 */
rt_uint32_t data_size; /* 數(shù)據(jù)塊大小 */};和郵箱例子相同的消息結(jié)構(gòu)定義,假設(shè)依然需要發(fā)送這樣一個消息給接收線程。在郵箱例子中,這個結(jié)構(gòu)只能夠發(fā)送指向這個結(jié)構(gòu)的指針(在函數(shù)指針被發(fā)送過去后,接收線程能夠正確的訪問指向這個地址的內(nèi)容,通常這塊數(shù)據(jù)需要留給接收線程來釋放)。而使用消息隊列的方式則大不相同:
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ā)送這個消息指針給 mq 消息隊列 */
rt_mq_send(mq, (void*)&msg_ptr, sizeof(struct msg));
}注意,上面的代碼中,是把一個局部變量的數(shù)據(jù)內(nèi)容發(fā)送到了消息隊列中。在接收線程中,同樣也采用局部變量進行消息接收的結(jié)構(gòu)體:
void message_handler(){ struct msg msg_ptr; /* 用于放置消息的局部變量 */
/* 從消息隊列中接收消息到 msg_ptr 中 */
if (rt_mq_recv(mq, (void*)&msg_ptr, sizeof(struct msg)) == RT_EOK)
{ /* 成功接收到消息,進行相應(yīng)的數(shù)據(jù)處理 */
}
}因為消息隊列是直接的數(shù)據(jù)內(nèi)容復(fù)制,所以在上面的例子中,都采用了局部變量的方式保存消息結(jié)構(gòu)體,這樣也就免去動態(tài)內(nèi)存分配的煩惱了(也就不用擔(dān)心,接收線程在接收到消息時,消息內(nèi)存空間已經(jīng)被釋放)。
例子說明:
下面例子是通過onenet 平臺發(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ā)送消息到消息隊列中 */
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ā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。











