简介
队列是一种任务到任务,任务到中断,中断到任务的一种数据交流机制。
队列中每一个数据叫做队列项目。
可以储存的做大数量的队列项目叫做队列长度。
1.数据存储
采用FIFO(先进先出)的储存缓冲机制。新数据放在老数据的后面,读取时先读取前面的数据。同时FreeRTOS还支持将数据写入队列头部,并可以指定是否覆盖已在队头的数据。
2.多任务访问
队列不输入某个特定的任务,可以在任何的任务或中断中往队列中写入消息,或者读取消息。
3.队列读取阻塞
在任务从队列中读取消息时,可以指定一个阻塞超时时间。读取时,如果队列为空,任务会进入到阻塞态,等待其他任务向队列中写入数据。当队列中存在数据或达到超时时间后任务恢复到就绪态。
(当多个任务因同一个空队列而进入到阻塞状态时,当队列有数据时,最先进入阻塞状态的任务会退出阻塞并接收消息,恢复到就绪态。)
4. 队列写入阻塞
与队列读取一样,在任务往队列中写入消息时,也可以指定一个阻塞超时时间。如果此刻队列已经满了,那么任务会进入到阻塞状态,直到达到时间或者有数据取出时,任务退出阻塞状态,恢复到就绪状态。
(同样,多个任务因写入满队列而进入到阻塞时,当有数据取出时,最先进入到阻塞状态的任务退出并正常写入。)
API函数
创建
动态创建队列
QueueHandle_t xQueueCreate(uxQueueLength, uxItemSize)
参数一:队列长度。
参数二:队列项目的大小(每个消息的大小,字节)。
返回值:创建成功,队列句柄。失败,NULL。
写入
在任务中往队列里写入消息。
函 数 xQueueGenericSend() 用 于 在 任 务 中 往 队 列 的 指 定 位 置 写 入 消 息。
BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition
);
参数一:待写入的队列。
参数二:待写入的消息。
参数三:阻塞超时时间。
参数四:写入的位置。
返回值:写入成功返回pdTRUE,失败errQUEUE_FULL。
为了方便使用,官方通过define固定参数四重定义了这个函数。
xQueueSend() 往队列的尾部写入消息
参数1:待写入的队列。参数二:待写入的消息。参数三:阻塞超时时间
xQueueSendToBack() 与xQueueSend一样
xQueueSendToFront() 往队列的头部写入消息 (紧急消息,直接放到最前面)
参数1:待写入的队列。参数二:待写入的消息。参数三:阻塞超时时间
xQueueOverwrite() 覆写队列消息(只用于队列长度为 1 的情况)
参数1:待写入的队列。参数二:待写入的消息。
在中断中
xQueueSendFromISR() 在中断中往队列的尾部写入消息
xQueueSendToBackFromISR() 与xQueueSend一样
xQueueSendToFrontFromISR() 在中断中往队列的头部写入消息
xQueueOverwriteFromISR() 在中断中覆写队列消息(只用于队列长度为 1 的情况)
参数1:待写入的队列
参数2:待写入的消息
参数3:是否需要任务切换
返回值:写入成功返回pdTRUE,失败errQUEUE_FULL。
读取
在任务中
1.从队列头部读取消息,并删除消息。
消息的读取是通过拷贝的形式传递的,具体拷贝数据的大小,为队列项目的大小。
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait
);
参数1:待读取的队列。
参数2:信息读取缓冲区。
参数3:阻塞超时时间。
返回值:读取成功返回pdTRUE,失败errQUEUE_FULL。
2.从队列头部读取消息,不删除信息。
此函数在成功读取消息后,并不会移除已读取的消息,这意味着,下次读取队列时,还能够读取到相同的内容。
BaseType_t xQueuePeek( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait);
参数1:待读取的队列。
参数2:信息读取缓冲区。
参数3:阻塞超时时间。
返回值:读取成功返回pdTRUE,失败errQUEUE_FULL。
在中断中
1.在中断中从队列头部读取消息,并删除消息
xQueueReceiveFromISR(QueueHandle_t xQueue,
void * const pvBuffer
);
参数一:待读取的队列
参数二:信息读取缓冲区
返回值:读取成功返回pdTRUE,失败errQUEUE_FULL。
2. 在中断中从队列头部读取消息,不删除消息。
xQueuePeekFromISR()
参数一:待读取的队列
参数二:信息读取缓冲区
返回值:读取成功返回pdTRUE,失败errQUEUE_FULL。
队列锁
在队列被上锁后,可以往队列中写入消息和读取消息,但是队列消息的读取和写入不会影响到队列读取和写入阻塞任务列表中的任务阻塞,队列的写入和读取阻塞任务列表会在队列解锁后,统一处理。
实验
任务一,扫描按键,将键值写入队列。
任务二,读取并显示队列。
创建队列:
QueueHandle_t xxx=NULL;
//创建消息队列
xxx = xQueueCreate(3,4);
往队列里写入数据:
//按键任务函数
void KEY_task(void *pvParameters)
{
u8 key=0;
BaseType_t xreturn = pdPASS;
while(1)
{
key=KEY_Scan();
if(key!=0)
{
//往xxx 队列中写入 key的值。
xreturn= xQueueSend(xxx,&key,0);
if(xreturn == pdPASS )
{
OLED_ShowString(2,5,"write true");
}
else
{
OLED_ShowString(2,5,"write false");
}
}
vTaskDelay(40);
}
}
读取队列中的数据:
void OLED_task(void *pvParameters)
{
BaseType_t xreturn=pdFALSE;
uint32_t key_val=0;
while(1)
{
// 任务句柄 存储数据的变量 等待时间
xreturn=xQueueReceive(xxx,&key_val,portMAX_DELAY);
if(xreturn == pdPASS)
{
OLED_ShowNum(3,3,key_val,2);
}
vTaskDelay(40);
}
}