以下内容为个人的初学记录,如有错误,欢迎指正
一、概述
- 队列用于数据的传输,数据按照**“先进先出”**(FIFO)的规则;一般情况下,数据被放入到底部(Back)指向的位置(除非使用向头部写入数据的函数),被头部(Front)指向时被读出
- 队列能够进行阻塞、唤醒,当接收任务发现队列为空时,会进入阻塞而不占用CPU,发送任务发现队列为满时也会进入阻塞,这样能够提高运行效率。
使用队列传输数据的方式有两种:
- 拷贝(将数据值复制到队列中);
- 引用(将数据的地址复制到队列中);
下面通过简单的练习来初步了解队列的基本内容,包含:
- 队列的动态创建
- 队列的阻塞访问
二、基本函数
队列创建
队列的创建(动态和静态),返回值是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在没有在写入失败时继续自增,也说明了【写入任务】进入了阻塞