FreeRTOS学习日记--消息队列(一般流程为:创建消息队列---写队列----读队列---删除队列)

简介(野火P17.5)

        ①消息队列是一种常用于任务间通信的数据结构,队列可以实现任务与任务、中断与任务间传递信息。同时消息队列也支持延时阻塞(读写都支持),当消息队列消息为空然后此时任务要读取(写入--即入队操作)该消息队列的消息,则可以设置指定阻塞的任务时间 xTicksToWait,若在此指定时间内消息队列一直为空,阻塞时间结束则任务将阻塞状态恢复至就绪态;若有新消息(若有其他任务读取该消息队列,则允许入队),则任务会读取消息并恢复就绪态。这是异步通信方式。同时也是FreeRTOS里任务间主要的通讯方式。

        ②消息队列遵从FIFO原则(也支持LIFO)。使用消息队列可以使一个/多个任务/中断例程发送一条或多条消息放入消息队列中,同时一个/多个任务可以从消息队列获取消息。当有多个任务阻塞在同一个消息队列时,若有新消息入队,则会以任务优先级来进行排序,任务优先级高的先出队。一般来说一个队列由多任务或中断写入是经常的事,但由多个任务读 出倒是用的比较少。

PS;中断只能发送消息,不能接收消息。因为接收消息需要设置阻塞时间,中断不需要阻塞。

  1.   可以允许不同长度(不超过队列节点最大值)的任意类型消息。
  2. 队列使用结束若此队列已经没有用了,可以使用队列删除函数删除(永久删除)。

        ③消息队列的内存空间大小在创建消息队列的时候就已经固定好了--即消息队列长度*单个消息大小。发送紧急消息时可以直接发送到队首,而发送普通消息时则发送的是队尾。发送到队列的消息是通过拷贝的方式实现的,说明队列中储存的是原始数据而不是数据的引用。

消息队列通用函数

在获取队列中的消息时候,我们必须要定义一个存储读取数据的地方,并且该数 据区域大小不小于消息大小,否则,很可能引发地址非法的错误。

①xQueueCreate() 消息队列创建函数(动态)

        说明:使用该函数必须将configSUPPORT_DYNAMIC_ALLOCATION 定义为 1 来使能,因为该, 数使用的是动态内存来分配消息队列的空间。在分配的RAM中,需要使用一部分的内存来储存队列的状态,剩下的作为队列消息的储存区域。

        函数原型:

        QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );

        1·消息大小是以字节为单位。2·该函数返回的是该消息队列的任务句柄。若创建失败,则返回NULL。原因可能是RAM分配失败。

xQueueCreateStatic()消息队列创建函数(静态)

        函数原型:

QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength, 
                                                            UBaseType_t uxItemSize,
                                                            uint8_t *pucQueueStorageBuffer,
                                                            StaticQueue_t *pxQueueBuffer );指向 StaticQueue_t 类型的变量,该变量用于存储队列的数据结构。

 ③vQueueDelete(QueueHandle_t xQueue) 消息队列删除函数

   注意:在有任务等待消息时,不应删除队列。同时消息队列删除函数也可以删除信号量。

xQueueSend()发送消息函数(等同于xQueueSendToBack()

        函数原型:        
BaseType_t xQueueSend(QueueHandle_t xQueue,
                                          const void * pvItemToQueue, 指向要发送到队尾的消息
                                          TickType_t xTicksToWait);队列满时,等待队列空闲的最大超时时间。
。如果 INCLUDE_vTaskSuspend 设置成 1 ,并且指定延时 为 portMAX_DELAY 将导致任务挂起(没有超时)。

xQueueSendFromISR()xQueueSendToBackFromISR()

        函数原型:

        BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,                                                                                                                  const void *pvItemToQueue,                                                                                                              BaseType_t *pxHigherPriorityTaskWoken);如果入队导致一个任务解锁,并且解锁的任务优先级高 于当前被中断的任务,则将*pxHigherPriorityTaskWoken 设置成 pdTRUE,然后在中断退出前需要进行一次上下 文切换, 去 执 行 被 唤醒 的 优 先 级 更高 的 任 务 。

⑥xQueueSendToFront()向队首发送消息

        函数原型:

        BaseType_t xQueueSendToFront( QueueHandle_t xQueue,                                                                                                                   const void * pvItemToQueue,                                                                                                             TickType_t xTicksToWait );如果 INCLUDE_vTaskSuspend 设置成 1,并且指定延时 为 portMAX_DELAY 将导致任务无限阻塞(没有超时)。

xQueueSendToFrontFromISR()

        函数原型:

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

xQueueReceive()  函数接收消息数据并删除

        函数原型:

        BaseType_t xQueueReceive(QueueHandle_t xQueue,
                                                       void *pvBuffer, 指向接收到要保存的数据。
                                                       TickType_t xTicksToWait);如果 INCLUDE_vTaskSuspend 设置成 1 ,并且指定延时 为 portMAX_DELAY 将导致任务无限阻塞(没有超时)。

⑨xQueuePeek()   函数接收消息且不删除

         函数原型:

          xQueuePeek( xQueue, pvBuffer, xTicksToWait );

xQueueReceiveFromISR() 消息会被删除

        函数原型:

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

    BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue, void *pvBuffer); 不会删除消息。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeRTOS消息队列是一种用于任务间通信的机制,可以在任务之间传递消息。队列中可以存储有限的、大小固定的数据项目,任务与任务、任务与中断之间要交流的数据保存在队列中,叫做队列项目。队列所能保存的最大数据项目数量叫做队列的长度,创建队列的时候会指定数据项目的大小和队列的长度。FreeRTOS中的信号量也是依据队列实现的,所以有必要深入了解FreeRTOS队列。 在FreeRTOS中,可以使用xQueueCreate()函数创建一个队列,该函数需要传入两个参数:队列的长度和每个队列项目的大小。创建队列后,可以使用xQueueSend()函数向队列中发送数据,使用xQueueReceive()函数从队列中接收数据。此外,还可以使用xQueuePeek()函数查看队列中的下一个数据项,而不将其从队列删除。 下面是一个简单的示例,演示如何在FreeRTOS中使用消息队列: ```c #include "FreeRTOS.h" #include "task.h" #include "queue.h" #define QUEUE_LENGTH 5 #define ITEM_SIZE sizeof(int) void vSenderTask(void *pvParameters) { QueueHandle_t xQueue; int i = 0; // 创建一个长度为QUEUE_LENGTH,每个项目大小为ITEM_SIZE的队列 xQueue = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE); while (1) { // 向队列中发送数据 xQueueSend(xQueue, &i, 0); // 延时一段时间 vTaskDelay(pdMS_TO_TICKS(500)); i++; } } void vReceiverTask(void *pvParameters) { QueueHandle_t xQueue; int iReceivedValue; // 获取发送任务创建队列句柄 xQueue = (QueueHandle_t)pvParameters; while (1) { // 从队列中接收数据 xQueueReceive(xQueue, &iReceivedValue, portMAX_DELAY); // 处理接收到的数据 printf("Received value: %d\n", iReceivedValue); } } int main(void) { QueueHandle_t xQueue; // 创建一个长度为QUEUE_LENGTH,每个项目大小为ITEM_SIZE的队列 xQueue = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE); // 创建发送任务 xTaskCreate(vSenderTask, "Sender", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); // 创建接收任务 xTaskCreate(vReceiverTask, "Receiver", configMINIMAL_STACK_SIZE, (void *)xQueue, tskIDLE_PRIORITY + 1, NULL); // 启动调度器 vTaskStartScheduler(); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值