一、消息隊列的應用場景
消息隊列可以應用於發送不定長消息的場合;隊列是FreeRTOS 主要的任務間通訊方式,可以在任務與任務間、中斷和任務間傳送信息;
二、消息隊列相關的函數
1、xQueueCreate() //動態創建消息隊列函數
2、xQueueCreateStatic() //靜態創建消息隊列函數
3、vQueueDelete() //消息隊列刪除函數
4、xQueueSend() //向隊列尾部發送一個隊列消息
5、xQueueSendToBack() //向隊列尾部發送一個隊列消息 等同於4
6、xQueueSendToFront() //向隊列頭部發送一個消息
7、xQueueSendFromISR() //向隊列頭部發送一個消息 用在中斷中
8、xQueueSendToBackFromISR() //向隊列頭部發送一個消息 用在中斷中 等同於7
9、xQueueGenericSend() //發送消息函數的原型
10、xQueueReceive() //從一個隊列中接收消息並把消息從隊列中刪除 決不能再中斷中使用
11、xQueuePeek() //從一個隊列中接收消息 不把消息從隊列中刪除
12、xQueueReceiveFromISR () //從一個隊列中接收消息並把消息從隊列中刪除 用在中斷中
13、xQueuePeekFromISR() //從一個隊列中接收消息 不把消息從隊列中刪除 用在中斷中
14、xQueueGenericReceive() //接收消息函數的原型
三、注意事項
1、必須在FreeRTOSConfig.h 中把 configSUPPORT_DYNAMIC_ALLOCATION 定義爲 1。
2、隊列是內核對象,具有自己獨立權限;
3、如果消息過於龐大,可以將消息的地址作爲消息進行發送、接收。
4、獲取隊列消息時,要定義一個大於或等於消息的大小。
5、隊列讀取採用的是先進先出(FIFO)模式,也支持後進先出(LIFO)模式
四、實驗數據
//FreeRTOS 庫
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
//硬件庫
#include "stm32f10x.h"
#include "bsp_usart.h"
//C庫
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/******************** 說 明 ************************
任務優先級: 數值越大 優先級高
****************************************************/
//堆棧大小
#define AppTaskCreate_Size 512 //創建任務的堆棧大小
#define ReceiveTask_Size 512 // 堆棧大小
#define SendTask_Size 512
//任務優先級 priority
#define AppTaskCreate_priority 1
#define ReceiveTask_priority 2
#define SendTask_priority 3
//申請任務句柄
static TaskHandle_t AppTaskCreate_Handle = NULL;
static TaskHandle_t Receive_Task_Handle = NULL;
static TaskHandle_t SendTask_Handle = NULL;
//內核對象句柄
QueueHandle_t Test_Queue =NULL;
#define QUEUE_LEN 4 //隊列的長度
#define QUEUE_SIZE 1 //隊列中每個消息的大小
//全局變量 串口部分
extern u8 USART1_BUFF[64];
extern u16 USART1_ReceiveLength;
extern u8 USART1_ReceiveEndFlag;
//任務聲明
static void AppTaskCreate(void); //用於創建任務
static void Receive_Task(void* pvParameters);//LED 任務的實現
static void Send_Task(void* pvParameters);
static void BSP_Init(void);//用於初始化板載相關資源
/******************主函數***********************/
int main(void)
{
BaseType_t xReturn = pdPASS;
BSP_Init();
printf(" usart send 1 or 2. task send queue data \r\n");
printf(" Receive task receive data in usart displey \r\n");
xReturn =xTaskCreate(
(TaskFunction_t ) AppTaskCreate, //任務函數入口
(const char* ) "AppTaskCreate", //任務名字
(uint16_t ) AppTaskCreate_Size, //任務棧大小
(void* ) NULL, //任務入口函數參數
(UBaseType_t ) AppTaskCreate_priority, //任務優先級
(TaskHandle_t* ) &AppTaskCreate_Handle); //任務控制塊指針
//啓動任務調度
if(pdPASS == xReturn)
vTaskStartScheduler();//啓動任務調度
else
return -1;
while(1);//正常 不會執行到這裏
}
//創建任務
static void AppTaskCreate(void)
{
BaseType_t xReturn = pdPASS;
taskENTER_CRITICAL();//進入臨界區
//創建 消息隊列 Test_Queue
Test_Queue =xQueueCreate((UBaseType_t )QUEUE_LEN,(UBaseType_t )QUEUE_SIZE);
if(NULL != Test_Queue)
printf("Create Test_Queue data queue ok!\r\n");
xReturn = xTaskCreate(
(TaskFunction_t ) Receive_Task, //任務函數
(const char*) "Receive_Task", //任務名稱
(uint32_t ) ReceiveTask_Size, //任務堆棧大小
(void* ) NULL, //傳遞給任務函數的參數
(UBaseType_t ) ReceiveTask_priority, //任務優先級
(TaskHandle_t*) &Receive_Task_Handle); //任務控制塊
if(pdPASS == xReturn )
printf("Receive_Task 創建任務成功\r\n");
xReturn = xTaskCreate(
(TaskFunction_t ) Send_Task, //任務函數
(const char*) "Send_Task", //任務名稱
(uint32_t ) SendTask_Size, //任務堆棧大小
(void* ) NULL, //傳遞給任務函數的參數
(UBaseType_t ) SendTask_priority, //任務優先級
(TaskHandle_t*) &SendTask_Handle); //任務控制塊
if(pdPASS == xReturn )
printf("Send_Task 創建任務成功\r\n");
vTaskDelete(AppTaskCreate_Handle);
taskEXIT_CRITICAL();
}
//接收打印任務
static void Receive_Task(void* parameter)
{
BaseType_t xReturn = pdTRUE;//定義一個創建信息返回值,默認爲pdTRUE
u8 r_queue;//定義一個接收消息的變量
while(1)
{
xReturn = xQueueReceive(Test_Queue, //消息隊列的句柄
&r_queue, //發送的消息內容
portMAX_DELAY);//等待時間 一直等
if(pdTRUE == xReturn)
printf("Receive data is %d\r\n\r\n",r_queue);
else
printf("Data receive error:0x%1x \r\n",xReturn);
}
}
//發送任務
static void Send_Task(void* pvParameters)
{
BaseType_t xReturn = pdPASS;//定義一個創建信息返回值
u8 sendData1 = 1;
u8 sendData2 = 2;
while(1)
{
if(USART1_ReceiveEndFlag == USART1ReceiveOk)
{
if(strstr((const char *)USART1_BUFF,"1") != NULL)
{
printf("send data is sendData1\r\n");
xReturn = xQueueSend(Test_Queue,&sendData1,0);
if(pdPASS == xReturn)
printf("send sendData1 data OK!\r\n\r\n");
}
else if(strstr((const char *)USART1_BUFF,"2") != NULL)
{
printf("send data is sendData2\r\n");
xReturn = xQueueSend(Test_Queue,&sendData2,0);
if(pdPASS == xReturn)
printf("send sendData2 data OK!\r\n\r\n ");
}
else
{
printf("Please enter 1 or 2! \r\n");
}
USART1_ReceiveEndFlag=0; //清標誌位
USART1_ReceiveLength =0; //清長度
memset(USART1_BUFF, 0, sizeof(USART1_BUFF));//清緩存
}
vTaskDelay(20);// 延時 20 個 tick
}
}
//硬件初始化函數
static void BSP_Init(void)
{
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
USART_Config();
}
// 串口中斷服務函數
u8 USART1_BUFF[64];
u16 USART1_ReceiveLength;
u8 USART1_ReceiveEndFlag=0;
void DEBUG_USART_IRQHandler(void)
{
uint8_t ucTemp;
if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
{
ucTemp = USART_ReceiveData(DEBUG_USARTx);
USART1_BUFF[USART1_ReceiveLength]=ucTemp;
if(USART1_BUFF[USART1_ReceiveLength]== 0x0a)//\n
{
if(USART1_BUFF[USART1_ReceiveLength-1] == 0x0d)//\r
{
USART1_ReceiveEndFlag=USART1ReceiveOk;//接收完成
}
}
else
{
++USART1_ReceiveLength;
}
//USART_SendData(DEBUG_USARTx,ucTemp);
}
}