欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > FreeRTOS 学习笔记>队列

FreeRTOS 学习笔记>队列

2025/9/28 3:14:09 来源:https://blog.csdn.net/qq_56044767/article/details/141532634  浏览:    关键词:FreeRTOS 学习笔记>队列

FreeRTOS 中的队列是任务之间进行通信的一种重要机制。通过队列,任务可以发送和接收数据,从而实现同步和数据共享。

队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息,实现任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列中读取消息,当队列中的消息是空时,读取消息的任务将被阻塞,用户还可以指定阻塞的任务时间xTicksToWait,在这段时间中,如果队列是空,该任务将保持阻塞状态以等待队列数据有效。当队列中有新消息时,被阻塞的任务会被唤醒并处理新消息:当等待的时间超过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转为就绪态。消息队列是一种异步的通信方式。

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

队列的基本操作

  1. 创建队列: 使用 xQueueCreate() 函数可以创建一个队列。该函数需要两个参数:队列的长度和每个队列项的大小。

    QueueHandle_t xQueue = NULL;
    xQueue = xQueueCreate(10, sizeof(int));
    
  2. 发送数据到队列: 使用 xQueueSend()xQueueSendToBack() 函数可以将数据发送到队列中。这些函数需要队列句柄、要发送的数据和等待时间作为参数。

    xQueueSend()用于向队列尾部发送一个队列消息。消息以拷贝的形式入队,而不是以引用的形式。该函数不能在中断服务程序里面调用,中断中需使用带有中断保护功能的xQueueSendFromISR()代替。

    xQueueSendToFront()用于向队列队首发送一个消息。消息以拷贝的形式入队。该函数不能在中断服务程序里面调用,中断中需使用带有中断保护功能的xQueueSendToFrontFromISR()代替。

    int data = 100;
    xQueueSend(xQueue, &data, portMAX_DELAY);//中断中需使用此函数
    xQueueSendFromISR(xQueue, &data, portMAX_DELAY);
    
  3. 从队列接收数据: 使用 xQueueReceive() 函数可以从队列中接收数据。该函数需要队列句柄、接收缓冲区和等待时间作为参数。

    xQueueReceive()用于从一个队列中接收消息并把消息从队列中删除。接收的消息是以拷贝 的形式进行的,所以我们必须提供一个足够大空间的缓冲区。该函数绝不能在中断服务程序里面被调用,而是必须使用带有中断保护功能的 xQueueReceiveFromISR ()来代替。

    int receivedData;
    xQueueReceive(xQueue, &receivedData, portMAX_DELAY);
    

队列的应用场景

队列在 FreeRTOS 中有广泛的应用,例如:

  • 任务间通信:一个任务可以将数据发送到队列中,另一个任务可以从队列中接收数据,从而实现任务间的通信。
  • 中断处理:中断服务程序可以将数据发送到队列中,任务可以从队列中接收数据,从而实现中断处理与任务之间的通信。
  • 事件管理:通过队列可以实现事件的管理和处理,例如按键事件、传感器事件等。

通过合理使用队列,可以提高系统的响应性和数据处理效率。

队列的高级操作

  1. 队列的删除: 使用 vQueueDelete() 函数可以删除一个队列。删除队列后,所有试图访问该队列的任务都会收到错误。

    if (xQueue == NULL) {} else {vQueueDelete(xQueue);
    }
    
  2. 阻塞时间: 当队列为空时,xQueueReceive() 函数可以选择阻塞一段时间,等待队列中有数据可用。当队列已满时,xQueueSend() 函数也可以选择阻塞,直到队列有空位。

实战示例

假设我们有一个传感器任务,它定期读取传感器数据并将其发送到队列中。另一个任务负责从队列中读取数据并进行处理。

传感器任务

void vSensorTask(void *pvParameters) {int sensorData;for (;;) {// 读取传感器数据sensorData = readSensor();// 发送数据到队列xQueueSend(xQueue, &sensorData, portMAX_DELAY);// 延时一段时间vTaskDelay(pdMS_TO_TICKS(1000));}
}

数据处理任务

void vProcessingTask(void *pvParameters) {int receivedData;for (;;) {// 从队列接收数据if (xQueueReceive(xQueue, &receivedData, portMAX_DELAY) == pdPASS) {// 处理接收到的数据processData(receivedData);}}
}

通过上述示例,我们可以看到如何通过队列在不同任务之间进行数据传输和处理,从而实现任务之间的协同工作。

欢迎指出博客中的错误,如果你觉得对你有用,记得点赞三连,有问题可留言,会及时回复

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词