作者:吾爱九-九九 | 来源:互联网 | 2023-02-06 04:39
一、消息队列的应用场景
消息队列可以应用于发送不定长消息的场合;队列是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
#include
#include
/******************** 说 明 ************************
任务优先级: 数值越大 优先级高
****************************************************/
//堆栈大小
#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();//启动任务调度elsereturn -1;while(1);//正常 不会执行到这里
}
//创建任务
static void AppTaskCreate(void)
{BaseType_t xReturn = pdPASS;taskENTER_CRITICAL();//进入临界区//创建 消息队列 Test_QueueTest_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;//定义一个创建信息返回值,默认为pdTRUEu8 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);elseprintf("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); }
}