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