【STM32】FreeRTOS 任务消息队列 和 中断消息队列的区别(六)

FreeRTOS 中的消息队列(Queue)是任务之间、任务与中断之间进行通信的核心机制之一。而当我们说:1、任务消息队列;2、中断消息队列; 其实我们说的是:谁在使用这个队列(任务 or 中断)进行发送或接收操作 ,以及使用的 API 函数是否安全、稳定、合适。

bash 复制代码
任务消息队列:
[Task A] --xQueueSend()--> [Queue] --xQueueReceive()--> [Task B]

中断消息队列:
[ISR Handler] --xQueueSendFromISR()--> [Queue] --xQueueReceive()--> [Task]
那为什么要区分任务和中断队列使用?

这是因为 中断中不能使用阻塞函数 ,也不能调用导致上下文切换的函数,因此 FreeRTOS 专门提供了 FromISR() 后缀的函数做中断安全的队列操作。

对比项 任务消息队列 中断消息队列
使用场景 任务 → 队列 → 任务 中断 → 队列 → 任务
入队函数 xQueueSend() xQueueSendToBack() xQueueSendToFront() xQueueSendFromISR() xQueueSendToBackFromISR() xQueueSendToFrontFromISR()
出队函数 xQueueReceive() xQueuePeek() xQueueReceiveFromISR() xQueuePeekFromISR() (极少数情况使用)
是否允许阻塞 ✅ 可以设置阻塞时间(如 portMAX_DELAY ❌ 中断中禁止阻塞,必须立即返回
是否触发任务切换 ✅ 自动调度(按优先级) ✅ 需手动触发:使用 portYIELD_FROM_ISR()
常见用途 任务间异步通信 / 消息传递 中断事件通知任务(如按键、串口等)
调用限制 无特殊限制 只能使用 FromISR 版本的 API 函数
任务消息队列
c 复制代码
// 任务 A 发送
xQueueSend(MyQueue, &data, 100);   // 最多等待 100 tick

// 任务 B 接收
xQueueReceive(MyQueue, &recvData, portMAX_DELAY);  // 永久等待直到有数据

RTOS 任务通信流程图:

中断消息队列
c 复制代码
// ISR 中断发送
void EXTI0_IRQHandler(void)
{
    uint8_t key = 1;
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    xQueueSendFromISR(MyQueue, &key, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken); // 必须添加
}

任务消息队列 适用于任务间通信 ,可以使用阻塞等待;中断消息队列 用于中断向任务发送事件 ,必须使用 FromISR() 函数,且不能有阻塞行为。

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!