引言
我們?cè)诼銠C(jī)開發(fā)中,每個(gè)函數(shù)之間進(jìn)行數(shù)據(jù)通信往往采用全局變量。而在嵌入式開發(fā)中。我們?cè)谶M(jìn)行進(jìn)程間通信的時(shí)候,往往采用消息隊(duì)列。對(duì)于操作系統(tǒng)來說,消息隊(duì)列是非常重要的一個(gè)數(shù)據(jù)結(jié)構(gòu)。本文將介紹一下,如何使用消息隊(duì)列進(jìn)行通信。
介紹
消息隊(duì)列概念
隊(duì)列又稱消息隊(duì)列,是一種常用于任務(wù)間通信的數(shù)據(jù)結(jié)構(gòu),隊(duì)列可以在任務(wù)與任務(wù)間、中斷和任務(wù)間傳遞信息,實(shí)現(xiàn)了任務(wù)接收來自其他任務(wù)或中斷的不固定長(zhǎng)度的消息,任務(wù)能夠從隊(duì)列里面讀取消息,當(dāng)隊(duì)列中的消息是空時(shí),讀取消息的任務(wù)將被阻塞,用戶還可以指定阻塞的任務(wù)時(shí)間 xTicksToWait,在這段時(shí)間中,如果隊(duì)列為空,該任務(wù)將保持阻塞狀態(tài)以等待隊(duì)列數(shù)據(jù)有效。當(dāng)隊(duì)列中有新消息時(shí),被阻塞的任務(wù)會(huì)被喚醒并處理新消息;當(dāng)?shù)却臅r(shí)間超過了指定的阻塞時(shí)間,即使隊(duì)列中尚無有效數(shù)據(jù),任務(wù)也會(huì)自動(dòng)從阻塞態(tài)轉(zhuǎn)為就緒態(tài)。消息隊(duì)列是一種異步的通信方式。
在FreeRTOS中的消息隊(duì)列函數(shù)
- 設(shè)定消息隊(duì)列的格式:osMessageQDef(myQueue, len, size);
- myQueue是消息隊(duì)列的名稱。
- len是消息隊(duì)列的長(zhǎng)度(有幾個(gè)消息)
- size是每個(gè)消息的大小,也就是每個(gè)元素的格式
-
創(chuàng)建消息:osMessageCreate(osMessageQ(myQueue01), NULL);
創(chuàng)建消息的函數(shù),實(shí)際上是調(diào)用了FreeRTOS的osMessageCreate()函數(shù),只不過HAL庫(kù)進(jìn)行了封裝。
-
向消息隊(duì)列發(fā)送消息
我們這里來介紹在中斷中發(fā)送消息。使用函數(shù)xQueueSendFromISR(QueueHandle,&Res,time);
其中:
- QueueHandle:消息隊(duì)列的句柄
- &Res:要發(fā)送的數(shù)據(jù)的地址
- time:阻塞時(shí)間,就是如果消息隊(duì)列滿的時(shí)候,任務(wù)應(yīng)該阻塞多久
-
接收消息隊(duì)列中的消息
xQueueReceive(QueueHandle,&queue_buffer,time);
- QueueHandle:消息隊(duì)列的句柄
- &queue_buffer:接收的消息要存放在的地址
- time:阻塞時(shí)間,就是如果消息隊(duì)列空的時(shí)候,任務(wù)應(yīng)該阻塞多久
-
查詢消息隊(duì)列中消息的數(shù)量
uxQueueMessagesWaiting(myQueue01Handle),可以返回消息隊(duì)列(句柄為myQueue01Handle)中消息的數(shù)量,返回值為整數(shù)。
實(shí)例
需求分析
此樣例我們使用PC充當(dāng)上位機(jī),上位機(jī)發(fā)送數(shù)據(jù)后,在串口中斷函數(shù)中將接收到的PC數(shù)據(jù)發(fā)送在消息隊(duì)列myQueue01Handle中,之后在一個(gè)接收線程中接收這個(gè)消息的內(nèi)容,并通過串口將接受到的消息的大小和內(nèi)容輸出出來。
發(fā)送消息
當(dāng)上位機(jī)PC下發(fā)數(shù)據(jù)后,串口中斷函數(shù)將接收到的數(shù)據(jù)發(fā)送在消息隊(duì)列中。
void USART3_IRQHandler(void)
{
uint8_t Res;
if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_RXNE)!=RESET)//檢測(cè)到有單個(gè)字節(jié)的中斷
{
HAL_UART_Receive(&huart3,&Res,1,0Xffff);
xQueueSendFromISR(myQueue01Handle,&Res,0)//發(fā)送消息
}
else if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)!=RESET)//空閑中斷(代表這一幀數(shù)據(jù)傳輸完了)
{
printf(" Receive a frame data.");
__HAL_UART_CLEAR_IDLEFLAG(&huart3)
}
接收消息
我們創(chuàng)建一個(gè)任務(wù),此任務(wù)的重要功能就是接收消息隊(duì)列中的消息。我們將接受到的消息的大小和內(nèi)容通過串口發(fā)送出來。沒有消息的時(shí)候,一直實(shí)現(xiàn)LED的閃爍。
void LEDToggleTesk(void const * argument)
{
/* USER CODE BEGIN LEDToggleTesk */
BaseType_t xReturn=pdTRUE;//定義一個(gè)創(chuàng)建消息返回值,默認(rèn)為pdTRUE
UBaseType_t num_queue ;
uint8_t Res[20];//存放我們接收到的一包數(shù)據(jù)
uint8_t queue_buffer;
int i=0;//接收數(shù)組下標(biāo)
for(;;)
{
i=0;
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
num_queue=uxQueueMessagesWaiting(myQueue01Handle);//獲取消息隊(duì)列中有多少數(shù)據(jù)
while(num_queue--)
{
xReturn=xQueueReceive(myQueue01Handle,&queue_buffer,0);//將消息隊(duì)列中的數(shù)據(jù)放在queue_buffer中
if(xReturn)
Res[i++]=queue_buffer;
}
if(i!=0)
printf(" count %d,LEDTask Receive %s",i,Res);//輸出接收消息的大小和內(nèi)容
osDelay(500);
}
}
現(xiàn)象
PC端發(fā)送123456789,MCU回復(fù)
Receive a frame data
count 8,LEDTask Receive 12345678
-
數(shù)據(jù)通信
+關(guān)注
關(guān)注
2文章
431瀏覽量
33754 -
嵌入式開發(fā)
+關(guān)注
關(guān)注
18文章
1028瀏覽量
47563 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4327瀏覽量
62569
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論