FreeRTOS-队列基础

以下内容为个人的初学记录,如有错误,欢迎指正

一、概述

  • 队列用于数据的传输,数据按照“先进先出”(FIFO)的规则;一般情况下,数据被放入到底部(Back)指向的位置(除非使用向头部写入数据的函数),被头部(Front)指向时被读出
  • 队列能够进行阻塞、唤醒,当接收任务发现队列为空时,会进入阻塞而不占用CPU,发送任务发现队列为满时也会进入阻塞,这样能够提高运行效率。
  • 当有多个任务被阻塞时,最先唤醒的是优先级最高的任务。如果优先级相等,则是最先唤醒阻塞时间最长的。

使用队列传输数据的方式有两种:

  1. 拷贝(将数据值复制到队列中);
  2. 引用(将数据的地址复制到队列中);

下面通过简单的练习来初步了解队列的基本内容,包含:

  1. 队列的动态创建
  2. 队列的阻塞访问

二、基本函数

队列创建

队列的创建(动态和静态),返回值是pdPASS/NULL:

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );

uxQueueLength:队列的长度;
uxItemSize:队列数据的大小(单位为byte)

QueueHandle_t xQueueCreateStatic( 
                           UBaseType_t uxQueueLength, 
                           UBaseType_t uxItemSize, 
                           uint8_t *pucQueueStorageBuffer, 
                           StaticQueue_t *pxQueueBuffer 
                       );

(与上面重复的不再描述)
pucQueueStorageBuffer:指向一个uint8_t数组的指针,该数组存储队列的消息数据
pxQueueBuffer:指向StaticQueue_t结构体的指针,该结构体存储队列的数据结构

写入队列函数,返回值是pdPASS/errQUEUE_FULL

BaseType_t xQueueSend( 
                  QueueHandle_t    xQueue, 
                  const void       *pvItemToQueue, 
                  TickType_t       xTicksToWait 
              ); 

pvItemToQueue:写入的数据的指针
xTicksToWait:阻塞时长

BaseType_t xQueueSendToBack( 
                          QueueHandle_t  xQueue, 
                          const void     *pvItemToQueue, 
                          TickType_t     xTicksToWait 
                      ); 

xQueueSend本身就是往队列的尾部执行写操作,因此和xQueueSendToBack的作用是一样的;另外有往头部进行写操作的函数

读取队列,返回值pdPASS/errQUEUE_EMPTY


BaseType_t xQueueReceive( QueueHandle_t xQueue, 
                          void * const pvBuffer, 
                          TickType_t xTicksToWait ); 

pvBuffer:指向存放读取数据的变量的指针
除了上述普通的队列读写函数,另外还有专门用在中断函数内的队列读写函数(xQueueSendToBackFromISR、xQueueSendToFrontFromISR、xQueueReceiveFromISR)

删除队列:

void vQueueDelete(QueueHandle_t xQueue);

三、练习

写入队列的任务函数该函数在每次发送数据后,会转置一次PC13电平。定义如下:

void SendTask(void* argument){
	uint16_t data = 0;
	while(1){
		vTaskDelay(100/portTICK_PERIOD_MS);
		BaseType_t SendStatus = xQueueSendToBack(TaskQueueHandle, &data, portMAX_DELAY);	
		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
		data++;
	}
}

读取队列的任务函数在PC14电平被人为置高电平后接收并打印数据,置低电平停止读取队列。定义如下:

void ReceiveTask(void* argument){
	uint16_t buffer;
	while(1){
		if( HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_14)==SET ){
			BaseType_t ReceiveStatus = xQueueReceive(TaskQueueHandle, &buffer, portMAX_DELAY);
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);
			if(ReceiveStatus == pdPASS)
				printf("receive = %u\r\n", buffer);
		}
	}
}

现象如下,其中红色电平信息为【写入任务】,绿色为【读取任务】。一开始PC14未置高,【写入任务】在发送5次数据后进入阻塞(后续的代码不会执行,包括电平不会翻转、data不会自增)
在这里插入图片描述
接收数据没有出现“断层”,说明data在没有在写入失败时继续自增,也说明了【写入任务】进入了阻塞
在这里插入图片描述

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值