引言
在嵌入式開發領域,STM32與FreeRTOS的結合應用極為廣泛。本文將探討如何在STM32上使用FreeRTOS實現消息隊列功能,助力高效任務通信與系統協作。
消息隊列定義
消息隊列是一種在 FreeRTOS 中用于任務間通信的機制。它允許任務將消息發送到隊列中,其他任務可以從隊列中接收這些消息。消息隊列可以存儲多種類型的數據,如整數、指針或結構體等。通過消息隊列,任務之間可以實現解耦,提高系統的可維護性和可擴展性。在 STM32 系統中,合理使用消息隊列可以有效協調多個任務的運行,優化資源分配,確保系統的高效穩定運行。
創建消息隊列
跟前面創建任務一樣,在起始函數中創建消息隊列
void MyTask(void *arg) //開始創建任務函數
{taskENTER_CRITICAL(); //進入臨界區 /* 創建Task_Queue */Task_Queue = xQueueCreate(QUEUE_LEN,QUEUE_SIZE);//xQueueCreate(隊列消息的長度,隊列消息的大小)xTaskCreate(MyTask1,"MyTask1",50,NULL,2,&MyTask1Handler);//動態方法創建任務1xTaskCreate(Receive_task,"Receive_task",50,NULL,3,&ReceiveTask_Handler);//創建接收消息任務xTaskCreate(Send_task,"Send_task",50,NULL,4,&SendTask_Handler); //創建發送消息任務vTaskDelete(MyTaskHandler); //刪除開始任務taskEXIT_CRITICAL(); //退出臨界區
}
xQueueCreate(*隊列長度,*隊列消息大小)
xQueueCreate()是FreeRTOS中用于創建消息隊列的函數,其函數原型為:
QueueHandle_t xQueueCreate(
UBaseType_t uxQueueLength,
UBaseType_t uxItemSize
);
參數uxQueueLength是隊列的長度,即隊列可以容納的最大消息數量。參數uxItemSize表示隊列中每個消息的大小,通常以字節為單位。該函數還有一個返回值,如果隊列創建成功,則返回隊列的句柄;如果失敗則返回NULL。
創建發送隊列消息任務函數
同樣先創建任務函數,然后調用xQueueSend()發送隊列消息函數,其函數原型如下:
BaseType_t xQueueSend(
QueueHandle_t xQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait
)
xQueueSend()是FreeRTOS 中用于向消息隊列發送消息的函數。它允許任務將數據發送到隊列中,供其他任務接收。參數xQueue指向要發送消息的隊列的句柄,這個句柄是用戶通過xQueueCreate創建時返回的。在上面已經定義成Task_Queue;參數*pvItemToQueue是一個指針類型,指向要發送到隊列的數據的值。參數xTicksToWait表示等待時間,這個時間通常是由systick滴答定時器提供,前面的文章已經講過,這里不再論述。如果隊列已滿,xTicksToWait()的行為取決于xTicksToWait()的值,如果為0,則函數返回pdFAIL;如果為非0值,任務將阻塞直到隊列有空間或等待時間已到,函數才會返回pdFAIL。(pdFAIL表示發送隊列消息失敗)
創建接收隊列消息任務函數
跟前面一樣,這里直接跳過。然后調用xQueueReceive()接收隊列消息函數。其函數原型為:
BaseType_t xQueueReceive(
QueueHandle_t xQueue, ? ?// 隊列的句柄
void *pvBuffer, ? ? ? ? ?// 用于存儲接收到的數據的緩沖區
TickType_t xTicksToWait ?// 等待隊列可用的時間
)
xQueueReceive()是 FreeRTOS 提供的一個函數,用于從隊列中接收數據。它通常用于任務之間通過隊列進行通信。參數xQueue表示隊列的句柄,指向要從中接收數據的隊列;參數*pvBuffer指向一個緩沖區,用于存儲從隊列中接收到的數據,緩沖區的大小盡量與隊列中存儲的數據大小一致。參數xTicksToWait? 跟上面一樣。
示例代碼
#include "myfreertos.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "queue.h"
#include "Usart.h"
#include "oled.h"
#include "Task.h"
#include "led.h"
#include "key.h"#define QUEUE_LEN 4 /* 隊列的長度,最大可包含多少個消息 */
#define QUEUE_SIZE 4 /* 隊列中每個消息大小(字節) */QueueHandle_t Task_Queue =NULL; //消息隊列句柄TaskHandle_t MyTaskHandler;//任務句柄TaskHandle_t MyTask1Handler;//任務1句柄TaskHandle_t SendTask_Handler; //發送消息句柄TaskHandle_t ReceiveTask_Handler;//接收消息句柄void MyTask(void *pvParameters); //聲明啟動函數void MyTask1(void *pvParameters); //聲明任務1函數void Send_task(void *pvParameters); //聲明發送消息函數void Receive_task(void *pvParameters); //聲明接收消息函數void Start_Task(void)
{xTaskCreate(MyTask,"MyTask",128,NULL,1,&MyTaskHandler);//動態方法創建任務vTaskStartScheduler();//啟動任務調動
}void MyTask(void *arg) //開始創建任務函數
{taskENTER_CRITICAL(); //進入臨界區 /* 創建Task_Queue */Task_Queue = xQueueCreate(QUEUE_LEN,QUEUE_SIZE);//xQueueCreate(隊列消息的長度,隊列消息的大小)xTaskCreate(MyTask1,"MyTask1",50,NULL,2,&MyTask1Handler);//動態方法創建任務1xTaskCreate(Receive_task,"Receive_task",50,NULL,3,&ReceiveTask_Handler);//創建接收消息任務xTaskCreate(Send_task,"Send_task",50,NULL,4,&SendTask_Handler); //創建發送消息任務vTaskDelete(MyTaskHandler); //刪除開始任務taskEXIT_CRITICAL(); //退出臨界區
}void MyTask1(void *arg) //任務1函數體
{
// u32 cnt=0; //定義變量while(1){OLED_ShowString(1,1,"Runing Task1");GPIO_ResetBits(GPIOC,GPIO_Pin_13);vTaskDelay(300);GPIO_SetBits(GPIOC,GPIO_Pin_13);vTaskDelay(900);
// if(++cnt>=10) //如果超過10次
// {
// if(MyTask1Handler!=NULL) //判斷句柄是否有效
// {
// vTaskDelete(MyTask1Handler); //刪除任務1
// MyTask1Handler=NULL; //清空句柄
// }
// }}
}//接收隊列消息任務函數
void Receive_task(void *pvParameters)
{BaseType_t xReturn = pdTRUE;/* 定義一個創建信息返回值,默認為pdTRUE */uint32_t r_queue; /* 定義一個接收消息的變量 */while(1){xReturn = xQueueReceive(Task_Queue,&r_queue,portMAX_DELAY); //xQueueReceive(隊列消息句柄,接收隊列消息的內容,等待時間)if(pdTRUE == xReturn) //判斷是否接收到消息OLED_ShowNum(2,1,r_queue,1); //顯示接收的消息}
}//發送隊列消息任務函數
void Send_task(void *pvParameters)
{BaseType_t xReturn = pdPASS;/* 定義一個創建信息返回值,默認為pdPASS */uint32_t send_data1 = 1; //定義發送的數據uint32_t send_data2 = 2; //定義發送的數據while(1){if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)==1){xReturn = xQueueSend(Task_Queue,&send_data1,10);//向隊列發送數據 if(pdPASS == xReturn) //判斷是否發送成功{OLED_ShowString(3,1,"Send_OK ");}}else{ xReturn = xQueueSend( Task_Queue,&send_data2,10); OLED_ShowString(3,1,"Send_OFF");}vTaskDelay(20);}
}
總結
本文介紹了 STM32 中 FreeRTOS 操作系統的消息隊列功能,包括其創建、發送、接收等操作方法,以及在嵌入式開發中的應用實例,有助于提高多任務通信效率(如有不足,歡迎指出)。