操作系统---FreeRTOS(队列集)

一、队列集简介

队列只能传输同一种数据,不同的任务之间需要传输不同的数据类型的消息时那么就需要使用队列集。

作用:用于对多个队列或者信号量进行监听,其中不管任何一个到来,都可以使任务退出阻塞状态。

假设:有个接受任务,使用到队列接收和信号量的获取,如下:

二、相关API函数

队列集使用流程:

1、启用队列集功能需要将宏configUSE_QUEUE_SETS 配置为 1;

2、创建队列集;

3、创建队列或信号量;

4、往队列集中添加队列或信号量;

5、往队列发送信息或释放信号量;

6、获取队列集的消息;

创建队列集函数:QueueSetHandle_t     xQueueCreateSet( const  UBaseType_t   uxEventQueueLength );

往队列集中添加队列,需要注意的时,队列再被添加到队列集之前,队列中不能有有效的消息:

BaseType_t    xQueueAddToSet( QueueSetMemberHandle_t       xQueueOrSemaphore ,                           QueueSetHandle_t           xQueueSet );

往队列集中移除队列,需要注意的时,队列在从队列集移除之前,队列中不能有有效的消息:

BaseType_t     xQueueRemoveFromSet( QueueSetMemberHandle_t      xQueueOrSemaphore ,                                   QueueSetHandle_t           xQueueSet );

此函数用于在任务中获取队列集中有有效消息的队列:

QueueSetMemberHandle_t     xQueueSelectFromSet( QueueSetHandle_t         xQueueSet,                                                                           TickType_t const         xTicksToWait );

三、队列集操作实验

工程代码:

main.c

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include <stdio.h>


//任务优先级
#define			START_TASK_PRIO	        1
//任务堆栈大小
#define			START_TASK_STACK_SIZE	128
//任务句柄
TaskHandle_t	start_task_handler;
//开始任务
void start_task(void *pvParameters);

//任务优先级
#define			TASK1_PRIO	        	2
//任务堆栈大小
#define			TASK1_STACK_SIZE		128
//任务句柄
TaskHandle_t	task1_handler;
//LED0任务
void task1(void *pvParameters);

//任务优先级
#define			TASK2_PRIO	        	3
//任务堆栈大小
#define			TASK2_STACK_SIZE		128
//任务句柄
TaskHandle_t	task2_handler;
//LED1任务
void task2(void *pvParameters);


QueueSetHandle_t queueset_handle;

QueueHandle_t    queue_handle;

QueueHandle_t    semaphore_handle;


 int main(void)
 {	

	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4 
	 GPIO_INIT();
	 KEY_INIT();
	 uart_init(9600);
	 
//创建开始任务
	xTaskCreate( (TaskFunction_t         )  start_task,				//任务函数指针
				 (char *                 )  "start_task", 			//任务函数名称
				 (configSTACK_DEPTH_TYPE )  START_TASK_STACK_SIZE,	//任务堆栈大小
				 (void *                 )  NULL,					//传递给任务函数的参数(一般为空)
				 (UBaseType_t            )  START_TASK_PRIO,		//任务优先级
				 (TaskHandle_t *         )  &start_task_handler );	//任务句柄

//开启任务调度				 
    vTaskStartScheduler();    

		 	  
}
 
 开始任务函数
void start_task(void *pvParameters)
{
	
	queueset_handle = xQueueCreateSet(2);							//创建队列集,可以存放2个队列
	if(queueset_handle != NULL)
	{
		printf("队列集创建成功\r\n");
	
	}
	queue_handle = xQueueCreate(1,sizeof(uint8_t));					//创建队列
	semaphore_handle = xSemaphoreCreateBinary();					//创建二值信号量
	
	xQueueAddToSet(queue_handle,queueset_handle);
	xQueueAddToSet(semaphore_handle,queueset_handle);
	
	//创建LED0任务
	xTaskCreate( (TaskFunction_t         )  task1,
				 (char *                 )  "task1", 
				 (configSTACK_DEPTH_TYPE )  TASK1_STACK_SIZE,
				 (void *                 )  NULL,
				 (UBaseType_t            )  TASK1_PRIO,
				 (TaskHandle_t *         )  &task1_handler );
	
	//创建LED1任务
	xTaskCreate( (TaskFunction_t         )  task2,
				 (char *                 )  "task2", 
				 (configSTACK_DEPTH_TYPE )  TASK2_STACK_SIZE,
				 (void *                 )  NULL,
				 (UBaseType_t            )  TASK2_PRIO,
				 (TaskHandle_t *         )  &task2_handler );
				 

				 				 
	//删除自己
	vTaskDelete(NULL);
	
}

//任务一释放二值信号量
void task1(void *pvParameters)
{
	u8 key = 0;
	BaseType_t err = 0;
	while(1)
	{
 		key = KEY_SCAN(0);
		if(key == KEY0_PRES)
		{
			err = xQueueSend(queue_handle,&key,portMAX_DELAY);
			if(err == pdPASS)
			{
				printf("往队列queue_handle写入数据成功!!\r\n");
			}
		}else if(key == KEY1_PRES)
		{
			err = xSemaphoreGive(semaphore_handle);
			if(err == pdPASS)
			{
				printf("释放信号量成功!!\r\n");
			}
		}
		vTaskDelay(10);
	}

}

/* 任务二,获取队列集的消息 */
void task2( void * pvParameters )
{
    QueueSetMemberHandle_t member_handle;
    uint8_t key;
    while(1)
    {
        member_handle = xQueueSelectFromSet( queueset_handle,portMAX_DELAY);
		
        if(member_handle == queue_handle)
        {
            xQueueReceive( member_handle,&key,portMAX_DELAY);
            printf("获取到的队列数据为:%d\r\n",key);
        }else if(member_handle == semaphore_handle)
        {
            xSemaphoreTake( member_handle, portMAX_DELAY );
            printf("获取信号量成功!!\r\n");
        }
    }
}


  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeRTOS是一个开源的实时操作系统内核,被广泛应用于嵌入式系统中。ESP32是一款具有双核处理器和Wi-Fi功能的芯片,通过使用ESP-IDF开发框架可以进行软件开发。在ESP32-IDF开发中,使用FreeRTOS的消息队列可以实现不同任务之间的通信。 在ESP32开发中,可以通过中断服务程序(Interrupt Service Routine,ISR)来发送消息到消息队列,并在任务中通过接收方法响应。 首先,我们需要创建一个全局的消息队列句柄,可以使用xQueueCreate函数来创建一个消息队列。例如,可以使用以下代码创建一个大小为10的消息队列: xQueueHandle messageQueue = xQueueCreate(10, sizeof(int)); 然后,在中断服务程序中,可以使用xQueueSendFromISR方法将消息发送到消息队列中。例如,可以使用以下代码将一个整数值发送到消息队列中: int value = 100; xQueueSendFromISR(messageQueue, &value, NULL); 在任务中,可以使用xQueueReceive方法从消息队列中接收消息并进行响应。例如,可以使用以下代码从消息队列中接收一个整数值并打印出来: int receivedValue; xQueueReceive(messageQueue, &receivedValue, portMAX_DELAY); printf("Received value: %d\n", receivedValue); 需要注意的是,在接收消息时,可以通过指定第三个参数来设置等待时间。例如,使用portMAX_DELAY表示无限等待,即直到接收到消息为止。 通过以上步骤,我们可以实现在ESP32开发中使用FreeRTOS消息队列进行中断服务消息发送与响应。这种方式可以实现不同任务之间的通信和同步,提高系统的并发性和实时性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值