FreeRTOS 消息队列使用教程
在 FreeRTOS 中,消息队列(Queue)是实现任务间通信的重要机制之一。通过队列,任务可以在不同优先级上下文中安全地传递数据。本文将详细介绍如何创建和使用 FreeRTOS 消息队列。
1. 创建队列 API
首先,使用 xQueueCreate
函数创建一个队列。该函数的定义在 queue.h
中,受控于动态内存申请的宏 configSUPPORT_DYNAMIC_ALLOCATION
(定义在 FreeRTOS.h
中),该宏默认是启用的。
2. 添加头文件
为了使用队列相关的 API 函数,您需要包含 queue.h
头文件:
#include "queue.h"
3. 声明并创建消息队列
确保包含正确的头文件,并在代码中声明和创建消息队列:
void createMyQueue(void)
{
if (queueHandle == NULL)
{
queueHandle = xQueueCreate(10, 64);
}
}
4. 发送函数
在 FreeRTOS 中,有多个函数可用于向队列发送消息。以下是一些常用的发送函数:
// 写入到队末,队列满后,超时不会插入
xQueueSend(xQueue, &item, portMAX_DELAY);
// 写入到队末,队列满后,超时不会插入
xQueueSendToBack(xQueue, &item, portMAX_DELAY);
// 覆盖队末,队列满后,超时不会插入
xQueueOverwrite(xQueue, &item);
// 写入到队首,队列满后,超时不会插入
xQueueSendToFront(xQueue, &item, portMAX_DELAY);
其中 xQueueSend
和 xQueueSendToBack
命名不同但内部实现是相同的:
5. 接收函数
以下是接收队列消息的两个常用函数:
// 从队列中取出消息,并删除该消息
xQueueReceive(xQueue, &item, portMAX_DELAY);
// 从队列中取出消息,但不删除队列中的该消息
xQueuePeek(xQueue, &item, portMAX_DELAY);
6. 队列满时的处理
6.1 使用 xQueueSend
发送消息,队列满了之后的处理
-
假设任务每 100 毫秒发送一次消息,我们可以使用以下方法验证效果:
-
使用
xQueuePeek
读取小时,每 1S 读取一次:
效果:读队首,入队末,所以读出来的数据一直没变
-
使用
xQueueReceive
读取小时,每 1S 读取一次:
效果:队列满后消息插入失败
xQueueSendToBack
的实际实现跟xQueueSend
完全一致,这里就不尝试了,队列满了,使用xQueueSendOverwrite
会如何?
6.2 使用 xQueueSendOverwrite
发送消息,队列满了之后的处理
假设任务每 100 毫秒使用 xQueueSendOverwrite
发送一次消息:
在接收端,同样可以使用 xQueuePeek
和 xQueueReceive
-
使用
xQueuePeek
读取小时,每 1S 读取一次,效果如下:队列满后重新覆盖
-
使用
xQueueReceive
读取小时,每 1S 读取一次,效果如下:
如果 xQueueSendToFront
发送时,队列满了,又会如何?
6.3 使用 xQueueSendToFront
发送消息,队列满了之后的处理
假设任务每 100 毫秒使用 xQueueSendToFront
发送一次消息:
在接收端,同样可以使用 xQueuePeek
和 xQueueReceive
:
-
使用
xQueuePeek
读取小时,每 1S 读取一次,效果如下:队列满后插入消息失败
-
使用
xQueueReceive
读取小时,每 1S 读取一次,效果如下:
7. 实际使用中的注意事项
在实际项目中使用 FreeRTOS 消息队列时,还需要考虑以下几点:
- 队列长度和项目需求匹配:确保队列长度设置合理,能够容纳任务间传递的消息量。
- 优先级反转:在高优先级任务频繁获取队列时,可能导致低优先级任务饥饿。可以通过使用信号量等机制来缓解这一问题。
- 实时性要求:根据系统的实时性要求,选择适当的发送和接收函数及其超时时间。
通过本文的介绍,我们详细了解了 FreeRTOS 消息队列的创建、发送和接收的不同方式及其行为特性。掌握这些基本操作后,您可以根据项目的具体需求,灵活应用消息队列来实现任务间的高效通信。
也可扫码关注博主同名公众号"不解之榬" 更多相关文章