10.FreeRTOS使用队列在任务间传输单种或多种类型任务

本文介绍了如何利用FreeRTOS在ESP32中创建多任务并使用队列进行任务间数据传输,包括基本的整数传输和结构体数据的传递,同时概述了FreeRTOS的关键API如xQueueCreate、xQueueSend和xQueueReceive。
摘要由CSDN通过智能技术生成

使用FreeRTOS在ESP32上实现任务间数据传输的简介与示例

介绍

在嵌入式系统开发中,任务间的数据传输是一项基本且常见的需求。ESP32作为一款功能强大的微控制器,搭载了FreeRTOS实时操作系统,为开发者提供了在多任务环境下进行数据传输的便利性。本文将介绍如何利用FreeRTOS在ESP32上实现任务间数据传输,并通过一个简单的示例演示其用法。

FreeRTOS简介

FreeRTOS是一个开源的实时操作系统内核,专为嵌入式系统设计。它提供了任务调度、信号量、消息队列等功能,使得开发者能够方便地创建多任务应用程序。在ESP32上,FreeRTOS被用作默认的操作系统,与Arduino框架无缝集成,为开发者提供了强大的多任务处理能力。

使用队列任务间数据传输

在多任务系统中,不同的任务之间需要进行数据交换和共享。为了实现任务间的数据传输,可以使用队列(Queue)、信号量(Semaphore)等机制。其中,队列是一种常用的数据传输方式,可以实现任务之间的异步通信,避免了直接共享全局变量所带来的竞态条件和数据一致性问题。

示例:任务间整数数据传输

下面是一个简单的示例,演示了如何在ESP32上使用FreeRTOS和Arduino框架,在两个任务之间传输整数数据:

传输单种类型:

#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>

// 定义队列的长度
#define QUEUE_LENGTH 5

// 定义队列句柄
QueueHandle_t queue;

// 定义任务句柄
TaskHandle_t Task1_Handle = NULL;
TaskHandle_t Task2_Handle = NULL;

// 定义任务函数
void Task1(void *pvParameters);
void Task2(void *pvParameters);

void setup() {
  Serial.begin(115200);

  // 创建队列
  queue = xQueueCreate(QUEUE_LENGTH, sizeof(int));

  // 创建任务1
  xTaskCreate(Task1, "Task1", 10000, NULL, 1, &Task1_Handle);

  // 创建任务2
  xTaskCreate(Task2, "Task2", 10000, NULL, 1, &Task2_Handle);
}

void loop() {
  // 什么都不做
}

// 任务1函数
void Task1(void *pvParameters) {
  int data = 0;

  while(1) {
    // 发送数据到队列
    xQueueSend(queue, &data, portMAX_DELAY);

    // 任务延时
    vTaskDelay(pdMS_TO_TICKS(1000));

    data++;
  }
}

// 任务2函数
void Task2(void *pvParameters) {
  int received_data;

  while(1) {
    // 从队列接收数据
    if(xQueueReceive(queue, &received_data, portMAX_DELAY) == pdTRUE) {
      Serial.println("Received Data: " + String(received_data));
    }
  }
}

在这里插入图片描述

传输多种类型:

#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>

// 定义队列的长度
#define QUEUE_LENGTH 5

// 定义队列句柄
QueueHandle_t queue;

// 定义任务句柄
TaskHandle_t Task1_Handle = NULL;
TaskHandle_t Task2_Handle = NULL;

// 定义数据结构
struct Data {
  int intValue;
  float floatValue;
};

// 定义任务函数
void Task1(void *pvParameters);
void Task2(void *pvParameters);

void setup() {
  Serial.begin(115200);

  // 创建队列
  queue = xQueueCreate(QUEUE_LENGTH, sizeof(Data));

  // 创建任务1
  xTaskCreate(Task1, "Task1", 10000, NULL, 1, &Task1_Handle);

  // 创建任务2
  xTaskCreate(Task2, "Task2", 10000, NULL, 1, &Task2_Handle);
}

void loop() {
  // 什么都不做
}

// 任务1函数
void Task1(void *pvParameters) {
  Data data;
  data.intValue = 10;
  data.floatValue = 3.14;

  while(1) {
    // 发送数据到队列
    xQueueSend(queue, &data, portMAX_DELAY);

    // 任务延时
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
}

// 任务2函数
void Task2(void *pvParameters) {
  Data received_data;

  while(1) {
    // 从队列接收数据
    if(xQueueReceive(queue, &received_data, portMAX_DELAY) == pdTRUE) {
      Serial.print("Received Int Value: ");
      Serial.println(received_data.intValue);
      Serial.print("Received Float Value: ");
      Serial.println(received_data.floatValue);
    }
  }
}


在这里插入图片描述

API

下面是对FreeRTOS队列常用API的总结:

  1. xQueueCreate()

    • 创建一个新的队列。
    • 参数:队列的长度和每个队列元素的大小。
    • 返回:成功时返回一个队列句柄(QueueHandle_t),失败时返回NULL。
  2. xQueueSend()

    • 向队列发送数据。
    • 参数:队列句柄、要发送的数据指针、超时时间。
    • 返回:如果成功发送数据,返回pdPASS;如果队列已满或者超时,返回pdFAIL。
  3. xQueueReceive()

    • 从队列接收数据。
    • 参数:队列句柄、接收数据的指针、超时时间。
    • 返回:如果成功接收到数据,返回pdPASS;如果队列为空或者超时,返回pdFAIL。
  4. uxQueueMessagesWaiting()

    • 获取当前队列中等待的消息数。
    • 参数:队列句柄。
    • 返回:当前队列中等待的消息数。
  5. uxQueueSpacesAvailable()

    • 获取当前队列中可用的空间数。
    • 参数:队列句柄。
    • 返回:当前队列中可用的空间数。
  6. vQueueDelete()

    • 删除一个队列及其相关资源。
    • 参数:要删除的队列句柄。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宁子希

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值