当前位置: 首页 > news >正文

2025最新超详细FreeRTOS入门教程:第四章 FreeRTOS消息队列

2025最新超详细FreeRTOS入门教程:第四章 FreeRTOS消息队列

摘要

在前几章中,我们学习了 任务的创建与管理。然而,在实际系统中,多个任务之间往往需要进行 通信与数据交换。例如:

  • 一个 传感器任务 负责采集数据
  • 一个 处理任务 负责计算与存储
  • 一个 通信任务 负责通过串口/网络发送

此时如果多个任务之间直接通过全局变量交互,极易导致数据竞争和逻辑混乱。
消息队列(Queue) 是 FreeRTOS 提供的最常用 任务间通信机制,它不仅能传递数据,还能实现任务间同步。

2025最新超详细FreeRTOS入门教程

文章目录

  • 2025最新超详细FreeRTOS入门教程:第四章 FreeRTOS消息队列
    • 摘要
    • 一、消息队列的基本概念
      • 特点
    • 二、队列的创建与删除
      • 1. 创建队列
      • 2. 删除队列
    • 三、队列的基本操作
      • 1. 发送数据
      • 2. 接收数据
      • 3. 中断安全版本
    • 四、队列使用示例
      • 示例:LED任务与UART任务通过队列通信
    • 五、队列的应用场景
      • 1. 任务间通信
      • 2. 任务与中断通信
      • 3. 事件传递
    • 六、队列超时与阻塞
    • 七、调试与监控
    • 八、常见问题与解决方法
    • 九、经验分享
    • 十、总结


一、消息队列的基本概念

消息队列是一个 先进先出(FIFO)缓冲区,可在 任务与任务中断与任务 之间传递消息。

特点

  • 可以存储固定大小的数据项
  • 写入队列的消息按顺序取出
  • 队列可作为任务间的同步机制
  • 可在中断中使用(ISR安全)
数据
数据
结果
传感器任务
消息队列
处理任务
通信任务

二、队列的创建与删除

1. 创建队列

QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,   // 队列长度(元素个数)UBaseType_t uxItemSize       // 单个元素大小(字节)
);

示例:创建一个可存储 10 个 int 的队列:

QueueHandle_t xQueue;
xQueue = xQueueCreate(10, sizeof(int));

2. 删除队列

void vQueueDelete(QueueHandle_t xQueue);

通常只在系统关闭或任务不再使用队列时调用。


三、队列的基本操作

1. 发送数据

BaseType_t xQueueSend(QueueHandle_t xQueue,const void *pvItemToQueue,TickType_t xTicksToWait
);
  • xTicksToWait:阻塞等待时间
    • 0:立即返回
    • portMAX_DELAY:无限等待

等价 API:

  • xQueueSendToFront() ——插入到队列头部
  • xQueueSendToBack() ——插入到队列尾部(默认行为)
  • xQueueOverwrite() ——覆盖队列(常用于长度=1的队列)

2. 接收数据

BaseType_t xQueueReceive(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait
);
  • 若队列为空,任务进入阻塞状态,直到有新数据

3. 中断安全版本

  • xQueueSendFromISR()
  • xQueueReceiveFromISR()

用于在 中断服务函数(ISR) 中收发数据。


四、队列使用示例

示例:LED任务与UART任务通过队列通信

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"QueueHandle_t xQueue;void vTaskProducer(void *pvParameters)
{int count = 0;while(1){count++;printf("发送数据: %d\n", count);xQueueSend(xQueue, &count, portMAX_DELAY);vTaskDelay(1000);}
}void vTaskConsumer(void *pvParameters)
{int value;while(1){if(xQueueReceive(xQueue, &value, portMAX_DELAY) == pdPASS){printf("接收数据: %d\n", value);}}
}int main(void)
{HAL_Init();SystemClock_Config();xQueue = xQueueCreate(10, sizeof(int));xTaskCreate(vTaskProducer, "Producer", 128, NULL, 2, NULL);xTaskCreate(vTaskConsumer, "Consumer", 128, NULL, 1, NULL);vTaskStartScheduler();while(1) {}
}

运行结果

  • Producer 每秒发送一个数字
  • Consumer 每秒打印接收到的数据

五、队列的应用场景

1. 任务间通信

  • 典型:传感器 → 数据处理 → 显示任务

2. 任务与中断通信

  • 中断快速采集数据 → 通过 xQueueSendFromISR() 发送到队列 → 后台任务处理

3. 事件传递

  • 使用队列传递命令字或事件码

六、队列超时与阻塞

ProducerQueueConsumerxQueueSend(数据)队列满? 阻塞等待xQueueReceive(数据)队列空? 阻塞等待返回数据ProducerQueueConsumer
  • 队列满时:发送任务等待 xTicksToWait 时间
  • 队列空时:接收任务等待 xTicksToWait 时间

七、调试与监控

FreeRTOS 提供队列状态查询函数:

UBaseType_t uxQueueMessagesWaiting(QueueHandle_t xQueue);
UBaseType_t uxQueueSpacesAvailable(QueueHandle_t xQueue);
  • uxQueueMessagesWaiting():返回当前队列中元素数量
  • uxQueueSpacesAvailable():返回剩余可用空间

八、常见问题与解决方法

问题可能原因解决方法
任务阻塞不运行队列满/空,阻塞时间过长调整 xTicksToWait
数据丢失使用非ISR安全API在中断中操作改用 xQueueSendFromISR
队列效率低队列长度过大合理设置长度,避免浪费RAM
队列传递复杂结构体报错传入指针而不是数据本身使用 memcpy 或定义固定结构体

九、经验分享

📌 开发建议

  1. 队列适合低速率数据通信;对于高速数据流,建议用 环形缓冲区DMA+事件通知
  2. 队列中的元素大小最好是 小数据(如整数、指针),不要传递大数组
  3. 对于“一对多”通信,更推荐 消息队列+事件组 结合使用
  4. 在调试时,使用 uxQueueMessagesWaiting() 观察队列状态,避免溢出

十、总结

通过本章学习,你已经掌握:

  • 创建、删除队列的方法
  • 使用 xQueueSend()xQueueReceive() 进行任务间通信
  • 在中断中安全操作队列
  • 监控队列状态的方法

消息队列是 RTOS 通信的核心工具,适合大多数“生产者—消费者”模型,为后续的 信号量与互斥量 学习打下了坚实的基础。


👉 下一章:2025最新超详细FreeRTOS入门教程:第五章 FreeRTOS信号量 ——我们将学习另一种重要的同步机制:信号量。


🔗 FreeRTOS专栏



文章转载自:

http://0UdyUr4b.rhwty.cn
http://pAPMIbvP.rhwty.cn
http://U6pS8g9q.rhwty.cn
http://Uo5gQtKZ.rhwty.cn
http://WXmcyKCJ.rhwty.cn
http://PjgEnRCk.rhwty.cn
http://w2wsDpSK.rhwty.cn
http://EosbhogF.rhwty.cn
http://3v1fyark.rhwty.cn
http://PwpcUOJH.rhwty.cn
http://thxfqeIn.rhwty.cn
http://sbRomknp.rhwty.cn
http://mHHOhxiv.rhwty.cn
http://YXThcFsJ.rhwty.cn
http://gmiFhFc5.rhwty.cn
http://xdtpWDDh.rhwty.cn
http://aMpba0IT.rhwty.cn
http://gQJ0S55d.rhwty.cn
http://FYJ3vJN7.rhwty.cn
http://523nbkTf.rhwty.cn
http://WZ1p8JqW.rhwty.cn
http://han2JYyf.rhwty.cn
http://11m8QxRv.rhwty.cn
http://Ha1s6pt7.rhwty.cn
http://YvBTUGKt.rhwty.cn
http://SSb06FyL.rhwty.cn
http://bW0SaCAA.rhwty.cn
http://47COqORT.rhwty.cn
http://noLasINQ.rhwty.cn
http://eW9P49WM.rhwty.cn
http://www.dtcms.com/a/371833.html

相关文章:

  • Rust 登堂 之 Drop 释放资源(十一)
  • 开关电源的原理、结构和实物入门篇-超简单解读
  • Environments
  • 上架商品合规流程有多条,有的长,有的短,有的需要审核,校验商品的合规性
  • 简单聊一聊js
  • 合格齿轴工艺工程师要修炼哪些功法?
  • LwIP入门实战 — 5 LwIP 的内存管理
  • 【三维生成】Matrix-3D:全向可探索的三维世界生成
  • DispatcherServlet 初始化过程:SpringMVC 的 “启动引擎” 详解
  • Simulink中使用Test sequence单元测试
  • 20250907-02:LangChain 架构和LangChain 生态系统包是什么
  • 大数据(非结构化数据,Spark,MongoDB)
  • FastAPI + LangChain 和 Spring AI + LangChain4j
  • Python基础语法篇:整数和浮点数,加减乘除怎么算?
  • 现成的AI模型:训练+评估框架汇总
  • 服务器断电引起的一例ORA-01207故障处理----惜分飞
  • 《MySQL基础——用户管理》
  • 【Linux】系统部分——进程间通信2(共享内存)
  • 【温室气体数据集】全球协作碳柱观测网络 COCCON
  • STM32 JLINK下载失败解决方案
  • JavaScript 中十种数组拷贝方法(从浅拷贝到深拷贝)
  • 04.事件中心模块
  • 【直接套模板】如何用 Web of Science 精准检索文献?
  • MCP与A2A
  • 数据库索引设计:在 MongoDB 中创建高效索引的策略
  • Shell 秘典(卷十)—— 服务器资源自动化监控脚本的设计与实现
  • 能源电力方向 的创业idea1
  • tf_keras包
  • PyTorch Lightning(训练评估框架)
  • Python进程,线程