目录

一、消息队列简介

消息队列的运作过程:

二、消息队列常用相关函数

1、队列创建

(1)动态创建xQueueCreate()

(2)静态创建xQueueCreateStatic()

(3)函数xQueueGenericCreate()

2、队列删除函数

3、入队函数

(1)任务级入队函数

(2)中断级入队函数

4、出队函数

(1)任务级

(2)中断级


一、消息队列简介

        消息队列是FreeRTOS中一种常用于任务间通信的数据结构,可以在任务与任务间、中断与任务间传递信息,所有任务都可以访问队列中的数据,相当于一个全局变量。任务从队列里面读取消息,当队列的消息为空时,读取消息的任务将被阻塞,阻塞时间可以自定义,阻塞时间内当队列有消息时任务将退出阻塞态,阻塞时间到达时也会退出阻塞态。

        消息队列内的消息支持先进先出原则(FIFO),也支持后进先出原则(LIFO)。消息数据可以是不同长度(不超过队列节点最大值)的任意类型消息。

消息队列的运作过程:

freertos消息队列示例_句柄

二、消息队列常用相关函数

1、队列创建

(1)动态创建xQueueCreate()

该函数是一个宏,最终调用的是xQueueGenericCreate()函数。

QueueHandle_t xQueueCreate ( const UBaseType_t uxQueueLength, //队列长度,队列的项目数
                            const UBaseType_t uxItemSize)    //每个项目(消息)的大小,字节为单位

返回值是QueueHandle_t类型的消息队列句柄,返回NULL则创建失败。

(2)静态创建xQueueCreateStatic()

该函数是一个宏,最终调用的是xQueueGenericCreateStatic ()函数。

QueueHandle_t xQueueCreateStatic ( const UBaseType_t uxQueueLength, //队列长度,队列的项目数
                                   const UBaseType_t uxItemSize, //每个项目(消息)的大小,字节为单位
                                   uint8_t *pucQueueStorage, //队列项目存储区,需定义,uint8_t类型的数组
                                   StaticQueue_t *pxQueueBuffer,)//指向StaticQueue类型的变量,保存队列结构体

返回值也是一个队列句柄,返回NULL则创建失败。

(3)函数xQueueGenericCreate()

这是动态创建的最终调用函数。

QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, //队列长度,队列的项目数
                                   const UBaseType_t uxItemSize, //每个项目(消息)的大小,字节为单位
                                   const uint8_t ucQueueType )//队列类型


队列类型定义:
#define queueQUEUE_TYPE_BASE                  ( ( uint8_t ) 0U )//普通的消息队列
#define queueQUEUE_TYPE_SET                   ( ( uint8_t ) 0U )//队列集
#define queueQUEUE_TYPE_MUTEX                 ( ( uint8_t ) 1U )//互斥信号量
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE    ( ( uint8_t ) 2U )//计数型信号量
#define queueQUEUE_TYPE_BINARY_SEMAPHORE      ( ( uint8_t ) 3U )//二值信号量
#define queueQUEUE_TYPE_RECURSIVE_MUTEX       ( ( uint8_t ) 4U )//递归互斥信号量

由此,相关的信号量的创建都是此函数完成的。

静态创建函数xQueueGenericCreate()也与此类似。

2、队列删除函数

void vQueueDelete( QueueHandle_t xQueue );

入口参数为队列句柄。

3、入队函数

freertos消息队列示例_freertos消息队列示例_02

(1)任务级入队函数

xQueueSend()、

xQueueSendToBack()、

xQueueSendToFront()

三个函数都有相同的入口参数,且最终实现函数都是xQueueGenericSend()。

BaseType_t xQueueSend( QueueHandle_t xQueue,
                       const void * pvItemToQueue,
                       TickType_t xTicksToWait
                       );

BaseType_t xQueueSendToBack( QueueHandle_t    xQueue,
                             const void       *pvItemToQueue,
                             TickType_t       xTicksToWait
                             );

BaseType_t xQueueSendToToFront( QueueHandle_t    xQueue,
                                const void       *pvItemToQueue,
                                TickType_t       xTicksToWait
                                );

入口参数:

xQueue :                  队列句柄;

pvItemToQueue:       发送的消息(地址)

xTicksToWait :        阻塞时间,当队列满的时候,该函数进入阻塞状态等待的时间,为0时不等待立即返回,为portMAX_DELAY时会一直等待。

返回值:

pdPASS:             发送信息成功

errQUEUE_FULL: 队列满发送失败

xQueueOverwrite():

BaseType_t xQueueOverwrite( QueueHandle_t xQueue,
                            const void * pvItemToQueue
                             );

该函数没有阻塞时间,也不需要阻塞。

通用入队函数xQueueGenericSend()

BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
                              const void * pvItemToQueue,
                              TickType_t xTicksToWait
                              BaseType_t xCopyPosition
                              );

入口参数:(其余与前面相同)

xCopyPosition:入队方式:

 queueSEND_TO_BACK  后向入队                 

 queueSEND_TO_FRONT 前向入队            

 queueOVERWRITE        覆写入队

(2)中断级入队函数

xQueueSendFromISR ()、

xQueueSendToBackFromISR ()、

xQueueSendToFrontFromISR ()、

xQueueOverwriteFromISR()

BaseType_t xQueueSendFromISR( QueueHandle_t xQueue,
                              const void *pvItemToQueue,
                              BaseType_t *pxHigherPriorityTaskWoken
                              );

BaseType_t xQueueSendToBackFromISR( QueueHandle_t xQueue,
                                    const void *pvItemToQueue,
                                    BaseType_t *pxHigherPriorityTaskWoken
                                    );

BaseType_t xQueueSendToFrontFromISR( QueueHandle_t xQueue,
                                     const void *pvItemToQueue,
                                     BaseType_t *pxHigherPriorityTaskWoken
                                     );

BaseType_t xQueueOverwriteFromISR( QueueHandle_t xQueue,
                                   const void * pvItemToQueue,
                                   BaseType_t *pxHigherPriorityTaskWoken
                                   );

入口参数:

xQueue :                   队列句柄;

pvItemToQueue:       发送的消息(地址)

pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换,只需提供变量保存即可。当此值为pdTRUE时需要进行一次任务切换。

返回值:

pdPASS:                发送信息成功

errQUEUE_FULL: 队列满发送失败

中断函数需要快进快出,因此中断函数里面不允许调用带有阻塞的函数

4、出队函数

出队即读取消息,读的都是消息队列的最后一项。

freertos消息队列示例_stm32_03

(1)任务级

xQueueReceive()、

xQueuePeek():

BaseType_t xQueueReceive( QueueHandle_t xQueue,
                          void *pvBuffer,
                          TickType_t xTicksToWait
                          );

BaseType_t xQueuePeek(  QueueHandle_t xQueue,
                        void * const pvBuffer,
                        TickType_t xTicksToWait
                        );

入口参数:

xQueue         队列句柄

pvBuffer        保存数据地址

xTicksToWait 阻塞时间

返回值:

pdPASS:                读取信息成功

errQUEUE_FULL: 读取信息失败

(2)中断级

xQueueReceiveFromISR()、

xQueuePeekFromISR():

BaseType_t xQueueReceiveFromISR( QueueHandle_t    xQueue,
                                 void             *pvBuffer,
                                 BaseType_t       *pxTaskWoken
                                 );


BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
                              void *pvBuffer,
                              );

入口参数:

xQueue         队列句柄

pvBuffer        保存数据地址

pxTaskWoken 标记退出此函数以后是否进行任务切换,只需提供变量保存即可。当此值为pdTRUE时需要进行一次任务切换

返回值:

pdPASS:                读取信息成功

errQUEUE_FULL: 读取信息失败