[FREERTOS]队列

本文介绍了FreeRTOS中的队列作为任务间通信的数据结构,解释了为何不用全局变量进行通信,阐述了队列的名词概念,如队列项目、队列长度,以及队列的特性,包括FIFO/LIFO数据传输、多任务访问和阻塞策略。同时,列举了相关的API函数,如创建队列、写队列和读队列的操作,并提供了在FreeRTOS中使用队列的实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.什么是队列

队列也称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务之间,中断和任务之间传递信息

2.传递信息为什么不用全局变量呢?

确实全局变量依然可以传递信息,但是如果全局变量改变的很频繁,某一任务处理数据比较缓慢,某一任务在处理数据的过程中改变了全局变量的值,就可能会导致某一任务获取的数据不正确,消息队列就像一条生产线似的,将数据放入队列中,任务从队列中读取数据,这样的话就算改变了数据的值,任务根据队列中的值来获取数据也能获取到正确的值

3.队列的几个名词

队列项目:队列中每一个数据

队列长度:队列能够存储项目(数据)的最大数量(创建队列时需要指定队列长度和队列项目大小)

队列的特点

1.数据的出入方式:

通常采用先入先出的数据缓冲方式(FIFO)也可以配置成后入先出的方式(LIFO) 

2.数据的传输方式

通常采用实际值传递,也就是将数据拷贝到队列中传递,也可以通过指针,通常传递较大的数据时采用指针传递

3.多任务访问

队列不属于任何一个任务,任何中断和任务都可以向队列发送/接收数据

4.出队/入队阻塞

当任务向队列中发送数据时,如果队列已满,可以指定一个堵塞时间:

0:不堵塞直接返回

0----port_MAX_Delay:等待设定的时间,如果超时还未能入队,就返回

port_MAX_Delay:死等,一直等到能够入队为止

与队列相关的API函数 

1.创建队列

QueueHandle_t  xQueueCreate(UBaseType_t uxQueueLength,UBaseType_t uxItemSize);

参数1:UBaseType_t uxQueueLength:队列中最大可存放的项目数

参数2:UBaseType_t uxItemSize:每个项目的大小

返回值如果创建成功就返回创建队列的句柄,如果创建队列所需内存无法分配就返回NULL

在cubeMX中配置好后会自动封装新的函数创建队列

声明定义两个任务和一个队列的句柄

2.写队列

xQueueSend();往队列尾部写入消息

xQueueSendToBack();与xQueueSend()效果相同

xQueueSendToFront();往队列头部写入消息

xQueueOverwrite();覆

写队列消息,只用于队列长度为1时

xQueueSendFromISR();往中断队列尾部写入消息

xQueueSendToBackFromISR();与xQueueSendFromISR();效果相同

xQueueSendToFrontFromISR()往中断队列头部写入消息

xQueueOverwriteFromISR();在中断中覆写队列消息,只用于队列长度为1时

BaseType_t xQueueSend{        

        QueueHandle_t       xQueue,

        const void*  pvItemToQueue,

        TickType_t  xTicksToWait

};

xQueue:队列的句柄,将数据项发到此队列

pvItemToQueue:待写入的数据

xTickToWait:阻塞超时时间

成功写入的话返回pdTRUE,否则返回errQUEUE_FULL       

4.读队列

 xQueueReceive();//从队列头部读取消息并删除此消息

 xQueuePeek();//从队列头部读取消息但不删除此消息

xQueueReceiveFromISR();//在中断中从队列头部读取消息,并删除消息

xQueueRPeekFromISR();在中断中从队列头部读取消息,不删除消息

BaseType_t xQueueReceive{        

        QueueHandle_t       xQueue,

        const void*  pvBuffer,

        TickType_t  xTicksToWait

};

xQueue:待读取的队列

pvItemToQueue:数据读取缓存区

xTickToWait:阻塞超时时间

成功写入的话返回pdTRUE,否则返回pdFALSE

按键key1发送数据给队列,按键key2接收队列数据

 

freertos.c

/*cubeMX配置的代码------------------------------↓*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
osThreadId taskSendHandle;
osThreadId taskReceiveHandle;
osMessageQId myQueueHandle;

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

void StartTaskSend(void const * argument);
void StartTaskReceive(void const * argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  *ppxIdleTaskStackBuffer = &xIdleStack[0];
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  /* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* Create the queue(s) */
  /* definition and creation of myQueue */
  osMessageQDef(myQueue, 16, uint16_t);
  myQueueHandle = osMessageCreate(osMessageQ(myQueue), NULL);

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of taskSend */
  osThreadDef(taskSend, StartTaskSend, osPriorityNormal, 0, 128);
  taskSendHandle = osThreadCreate(osThread(taskSend), NULL);

  /* definition and creation of taskReceive */
  osThreadDef(taskReceive, StartTaskReceive, osPriorityNormal, 0, 128);
  taskReceiveHandle = osThreadCreate(osThread(taskReceive), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}
/*cubeMX配置的代码------------------------------↑*/







/*需要手动敲的代码------------------------------↓*/
void StartTaskSend(void const * argument)
{
  /* USER CODE BEGIN StartTaskSend */
	uint16_t buf = 100;
	BaseType_t status;
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)//消抖
			{
				status = xQueueSend(myQueueHandle,&buf,0);
				if(status == pdTRUE)/如果发送成功会返回pdTRUE
				{
					printf("send success:%d\r\n",buf);
				}else
				{
					printf("send error\r\n");
				}
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET);
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskSend */
}

/* USER CODE BEGIN Header_StartTaskReceive */
/**
* @brief Function implementing the taskReceive thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskReceive */
void StartTaskReceive(void const * argument)
{
  /* USER CODE BEGIN StartTaskReceive */
		uint16_t buf;
	BaseType_t status;
  /* Infinite loop */
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)
		{
			osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)//消抖
			{
				status = xQueueReceive(myQueueHandle,&buf,0);
				if(status == pdTRUE)//如果接收成功会返回pdTRUE
				{
					printf("read success:%d\r\n",buf);
				}else
				{
					printf("read error\r\n");
				}
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET);
		}
    osDelay(10);
  }
  /* USER CODE END StartTaskReceive */
}
/*需要手动敲的代码------------------------------↑*/

 uart.c

#include "usart.h"

/* USER CODE BEGIN 0 */
#include <string.h>
#include <stdio.h>
int fputc(int ch,FILE*f)//printf重定向
{
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart1,temp,strlen((const char*)temp),0xffff);
	return ch;
}

重定向一定记住 勾选Use MicroLIB!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值