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