一.队列的简介
1.什么是队列?
队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务之间、中断与任务之间传递消息。
2.为什么不直接使用全局变量?
如果使用全局变量,任务1修改变量a,等待任务3处理,任务3处理速度很慢,在处理的过程中,任务2修改变量a,这会导致任务3得到的数据不准确。故需要使用队列传递数据。
关于队列的几个名词:
队列项目:队列中的每一个数据
队列长度:队列能够存储队列项目的最大数量
创建队列时需要指定队列项目的大小和队列的长度
3.队列的特点
(1)数据入队出队的方式:通常使用先进先出(FIFO)的数据缓存机制,先入队的数据先读取,也可以使用后进先出(LIFO)的方式,但是不常用。
(2)数据传递方式:采用实际值传递,将数据拷贝到队列中进行传递,也可以通过传递指针,在传递较大的数据时,采用指针传递。
(3)多任务访问:队列不属于某个任务,任何任务和中断都可以向队列发送/读取数据
(4)出队、入队阻塞:当任务向一个队列发送消息时,可以指定一个阻塞时间,当队列已满无法入队时,设置阻塞时间:0 -> 直接返回不等待 (出队阻塞与入队阻塞类似)
0~port_MAX_DELAY:等待设定的阻塞时间,若该时间内无法入队,超时后返回
port_MAX_DELAY:死等,一直等待,直到可以入队
二.队列相关的API函数
1.创建队列 xQueueCreate()
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,
UBaseType_t uxItemSize);
参数:
uxQueueLength:队列长度
uxItemSize: 队列中每个项目的大小(以字节为单位)
返回值:队列创建成功,返回队列句柄; 队列创建失败,返回NULL
2.写队列/入队列
BaseType_t xQueueSend( QueueHandle_t xQueue,
const void * pvItemToQueue,
TickType_t xTicksToWait);
BaseType_t xQueueSendToBack(QueueHandle_t xQueue,
const void* pvItemToQueue,
TickType_t xTicksToWait);
BaseType_t xQueueSendToToFront(QueueHandle_t xQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait);
参数:
xQueue: 队列句柄,指明要向哪个队列发送数据
pvItemToQueue:待写入的数据
xTicksToWait: 阻塞超时时间
返回值:队列写入成功,返回pdPASS 写入失败,返回errQUEUE_FULL
3.读队列/出队列
portBASE_TYPE xQueueReceive( xQueueHandle xQueue,
void *pvBuffer,
portTickType xTicksToWait );
参数:
pxQueue:待读取数据的队列句柄
pvBuffer: 数据读取缓冲区。
xTicksToWait:阻塞超时间 若 INCLUDE_vTaskSuspend 定义为1 ,死等
返回值:成功,返回pdTRUE 失败,返回pdFALSE
综合实验(HAL库):
1.创建一个队列,按下KEY0向队列发送数据,按下KEY1读取队列数据
2.CubeMX配置
3.代码部分
综合实验(库函数):
1.设计4个任务:start_task,task1,task2,task3
2.创建队列
(1)在freertos_demo.c中包含头文件queue.h
(2)定义2个队列句柄
(3)创建队列
1.队列长度为2,项目大小为1个字节(8位)->key键值为长度1个字节,故设为1个字节
2.队列长度为1,项目大小为4个字节(char *)->定义一个char型的数组,存放大数据
(4)任务1执行内容
key的键值宏定义
(5)任务2执行内容
(6)任务3执行内容