• 方案介绍
  • 附件下载
  • 相关推荐
申请入驻 产业图谱

23.1.1-消息队列的概念和函数 FreeRTOS 项目 FreeRTOS学习笔记

02/16 08:24
1559
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

联系方式.txt

共1个文件

这个是全网最详细的STM32项目教学视频。
第一篇CSDN文章在这里在这里:
75


STM32智能小车V3-STM32入门教程-openmv与STM32循迹小车-stm32f103c8t6-电赛 嵌入式学习 PID控制算法 编码器电机 跟随

V3:HAL库开发、手把手教学下面功能:PID速度控制、PID循迹、PID跟随、遥控、避障、PID角度控制、openmv视觉控制、电磁循迹、FreeRTOS、K210视觉智能车(更新中)、K230视觉智能车(更新中)、MSPM0G3507视觉智能车(更新中)

在这里插入图片描述

23.1.1-消息队列的概念和函数

消息队列概念

消息队列简称队列,是一种常用于任务间通信的数据结构。

如下图:消息队列可以在任务与任务间、中断与任务间传递消息,实现任务接收来自其它任务或中断的不固定长度的消息。
在这里插入图片描述
相比于裸机的全局数组,使用消息队列有如下优势:

  • 消息队列具有超时机制,可以让 FreeRTOS 内核有效地管理任务。
  • 使用消息队列可以防止多任务的访问冲突、防止数据竞争 出现错误.
  • 使用消息队列可以有效地解决中断服务程序与任务之间消息传递的问题,使用全局数组的话,任务得不断去监测标志位以获取数据
  • 消息队列具有FIFO与LIFO储存机制,方便处理数据。

消息队列的通信机制

消息队列是一种异步的通信方式。

任务能够从队列中读取消息,当队列中的消息为空时,读取消息的任务将被阻塞。用户可以指定阻塞的任务时间 xTicksToWait,在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。当队列中有新消息时,被阻塞的任务会被唤醒并处理新消息;当等待的时间超过指定的阻塞时间,即使队列中没有有效数据,任务也会自动从阻塞态转为就绪态。

通过消息队列服务,任务或中断服务可以将一条或多条消息放入消息队列中。同样,一个或多个任务可以从消息队列中获得消息。当有多个消息发送到消息队列时,通常是将先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入消息队列的消息,即先进先出原则(FIFO),FreeRTOS的队列也支持后进先出原则(LIFO)。

FreeRTOS中消息队列特性

  • 消息支持先进先出方式排队,支持异步读写工作方式
  • 读写队列均支持超时机制
  • 消息支持后进先出方式排队,向队首发送消息(LIFO)
  • 可以允许不同长度(不超过队列节点最大值)的任意类型消息
  • 一个任务能够从任意一个消息队列接收和发送消息
  • 多个任务能够从同一个消息队列接收和发送消息
  • 当队列使用结束后,可以通过删除队列函数进行删除

消息队列应用场景

消息队列可用于发送不定长消息的场合。

队列是FreeRTOS 主要的任务间通信方式,可以在任务与任务间、中断和任务间传送信息,发送到队列的消息是通过复制方式实现的,这意味着队列存储的数据是原始数据,而不是原始数据的引用。

消息队列的常用API函数

创建消息队列

xQueueCreate():

QueueHandle_t xQueueCreate( 
    UBaseType_t uxQueueLength, //队列的最大长度,表示队列可以容纳的元素个数。
    UBaseType_t uxItemSize //队列中每个元素的大小(以字节为单位)。即每个元素占用的内存空间。可以是任何数据类型的大小,例如 sizeof(int)、sizeof(char) 等。
);
QueueHandle_t 返回值:
成功:返回队列句柄(QueueHandle_t),这个句柄将用于后续的队列操作(如发送和接收数据)。
失败:如果创建队列失败,返回 NULL。       
任务中向队列发送数据-不会覆盖原有数据

xQueueSend() :

A

BaseType_t xQueueSend( 
    QueueHandle_t xQueue, //队列句柄,表示你要操作的队列。
    const void * pvItemToQueue, //指向要发送到队列的数据的指针。数据会被复制到队列中。
    TickType_t xTicksToWait //等待队列空间的时间。如果队列满了,xQueueSend 会等待空闲空间。此值可以是 0 表示非阻塞操作,portMAX_DELAY 表示无限等待,或者其他自定义的等待时间。
);
BaseType_t 返回值:
pdPASS:成功将数据发送到队列。
errQUEUE_FULL:队列已满,无法立即放入数据。如果 xTicksToWait 设置为 0,则是非阻塞的,队列满时返回 errQUEUE_FULL。
errQUEUE_BLOCKED:如果队列满且设置了阻塞时间,任务会被阻塞直到有空间。                     
任务中向队列发送数据-会强制覆盖原有数据
BaseType_t xQueueOverwrite( QueueHandle_t xQueue,       //队列句柄
                           const void *pvItemToQueue    //要发送到队列的数据指针
                          );

函数作用:函数会强制将新数据写入队列,并覆盖队列中原有的元素。
返回值:
如果操作成功,返回 pdPASS。
如果队列为空或出现其他错误,返回 errQUEUE_FULL。
任务中接收队列数据-会从队列中移除该数据

xQueueReceive():

BaseType_t xQueueReceive( 
    QueueHandle_t xQueue, //要接收数据的队列句柄。这个句柄是在创建队列时由 xQueueCreate() 返回的。它标识了队列。
    void * const pvBuffer, //指向接收数据存储位置的指针。数据将被放置到这个缓冲区中,缓冲区的大小应当足够存储队列中每个消息的内容。
    TickType_t xTicksToWait//指定任务在队列中没有数据时应该等待的时间,单位是 FreeRTOS 系统中的“滴答”(tick)。如果设置为 0,则表示不等待,队列为空时 xQueueReceive() 将立即返回。如果设置为 portMAX_DELAY,表示无限期等待,直到队列中有数据。
);

返回值:
pdPASS:
如果成功从队列接收数据,返回 pdPASS(即 1)。
errQUEUE_EMPTY:
如果队列为空且任务设置的等待时间为 0,或者任务等待超时,返回 errQUEUE_EMPTY(即 0)。
任务中接收队列数据-但不会将数据移除
BaseType_t xQueuePeek( QueueHandle_t xQueue,//这是队列的句柄,指向你想要查看的队列。队列句柄是通过 xQueueCreate() 创建队列时获得的。
                      void * pvBuffer, //这是一个指向接收数据的缓冲区的指针,队列中的数据会被复制到这个缓冲区。注意,数据将从队列复制到该缓冲区中,但不会删除队列中的数据。
                      TickType_t xTicksToWait //如果队列为空,xQueuePeek() 会阻塞直到队列中有数据可用。如果 xTicksToWait 为 0,表示函数不会阻塞(即,如果队列为空,函数会立即返回)。如果为 portMAX_DELAY,则函数会一直等待,直到队列有数据可用。
                     );

返回值
pdPASS:如果成功地从队列中“查看”到数据,则返回 pdPASS。
errQUEUE_EMPTY:如果队列为空且 xTicksToWait 为 0,表示没有数据可查看,函数将返回 errQUEUE_EMPTY。
其他返回值:在发生错误时,可能会返回其他错误码。
    
如果队列为空, xQueuePeek() 会阻塞直到队列中有数据可用。如果 xTicksToWait 为 0,表示函数不会阻塞(即,如果队列为空,函数会立即返回)。如果为 portMAX_DELAY,则函数会一直等待,直到队列有数据可用。
中断中向队列发送数据-不会覆盖原有数据

xQueueSendFromISR():

BaseType_t xQueueSendFromISR(
    QueueHandle_t xQueue,         // 要发送数据的队列句柄
    const void * pvItemToQueue,   // 指向要发送的数据的指针
    BaseType_t * pxHigherPriorityTaskWoken // 用于指示是否唤醒了更高优先级的任务
);

**返回值**

- **`pdPASS`**: 表示队列成功接收数据并且返回成功。
- **`errQUEUE_FULL`**: 表示队列已满,无法发送数据到队列中。
    
在 FreeRTOS 中,默认情况下, xQueueSendFromISR() 会根据队列是否已满来判断是否将数据写入队列。如果队列已经满了,并且没有使用 队列覆盖机制,它会返回 errQUEUE_FULL,并且数据不会被写入队列。如果希望强制写入队列使用 xQueueOverwriteFromISR()
中断中向队列发送数据-会且强制覆盖原有数据
BaseType_t xQueueOverwriteFromISR(
    QueueHandle_t xQueue,                  //要操作的队列句柄(通过 xQueueCreate() 创建)。
    const void *pvItemToQueue,			   //指向要发送到队列的数据的指针。数据的大小由创建队列时指定的大小(uxItemSize)决定。
    BaseType_t *pxHigherPriorityTaskWoken   // 用于指示是否需要任务切换的标志
);
BaseType_t  返回值
pdPASS:表示数据已成功写入队列(覆盖旧数据)。
此函数没有返回 errQUEUE_FULL,因为它总是会覆盖数据,即使队列已满。
    
FreeRTOS 中的一个特殊队列操作函数,专门用于在 中断服务例程(ISR)中 向队列写入数据,并 强制覆盖队列中的现有数据。也就是在队列已经满的时候依旧可以写入最新数据。
中断中从队列接收数据-会从队列中移除该数据

**xQueueReceiveFromISR(): **

BaseType_t xQueueReceiveFromISR(
    QueueHandle_t xQueue,                    // 要从中接收数据的队列句柄
    void * const pvBuffer,                   // 用于存储接收到的数据的缓冲区
    BaseType_t * const pxHigherPriorityTaskWoken // 用于指示是否需要任务切换的标志
);

返回值:

- **`pdPASS`**:表示从队列成功接收到数据。
- **`errQUEUE_EMPTY`**:表示队列为空,没有数据可以接收。

xQueueReceiveFromISR() 在 接收数据时会 接收完数据后,会将该数据移除
中断中从队列接收数据-但不移除该数据
BaseType_t xQueuePeekFromISR( 
    QueueHandle_t xQueue,                //队列的句柄,指定你要从中读取数据的队列
    void *pvBuffer, 	                //指向存储接收数据的缓冲区的指针。接收到的数据会存放在这里,但不会从队列中移除。
    BaseType_t *pxHigherPriorityTaskWoken //指向 BaseType_t 类型的变量,标记是否有高优先级任务被唤醒。如果在调用过程中有高优先级任务就绪,FreeRTOS 会根据这个标志决定是否进行任务切换。
);
xQueuePeekFromISR() 从队列中读取数据,但 不移除数据。这意味着即使读取了队列中的数据,队列中原来的数据仍然保留,其他任务或中断可以继续读取队列中的数据。
返回值:
pdPASS:表示成功接收到数据。
errQUEUE_EMPTY:表示队列为空,没有接收到任何数据。

 

  • 联系方式.txt
    下载
点赞
收藏
评论
分享
加入交流群
举报

相关推荐

方案定制

去合作
方案开发定制化,2000+方案商即时响应!