SOC-ESP32S3部分:11-任务创建

飞书文档https://x509p6c8to.feishu.cn/wiki/EH3owsPahisvl6kL6k3cqaQ3n0g  在我们学习单片机的时候,main函数入口中一般有一个while大循环在不停轮询,如果我们需要实现多种不同的业务,就需要用到状态机,根据不同时刻的要求执行不同的代码,虽然可以实现需求,但这种情况下代码是比较臃肿的。试想下,如果我们可以开启多个while循环,每个while循环负责不同的业务,这样实现复杂的业务是不是更容易了呢?

void main1(){
    while (1)
    {
        //执行某些操作
    }
}

void main2(){
    while (1)
    {
        //执行某些操作
    }
}

在 FreeRTOS 中,任务(Task) 可以通俗地理解为一个独立的“小程序”或“小工人”,每个任务都有自己的工作内容和优先级,它们共同协作完成整个系统的功能。

1、任务是什么?

任务是一个独立的执行单元

每个任务就像一个小工人,负责完成特定的工作。例如:

  • 一个任务负责读取传感器数据。
  • 一个任务负责控制 LED 灯。
  • 一个任务负责处理网络通信。

任务有自己的运行空间

每个任务都有自己的栈(Stack),用于存储临时变量和函数调用信息。任务之间是相互独立的,不会互相干扰。

任务可以同时运行

虽然 ESP32 是单核或双核处理器,但 FreeRTOS 通过快速切换任务,让多个任务看起来像是同时运行的(这叫做“并发”)。

假设我们有一个智能家居系统,需要完成以下功能:

  • 读取温度传感器的数据。
  • 根据温度控制风扇的开关。
  • 将温度数据发送到云端。

我们可以创建 3 个任务:

任务 1:读取温度
每隔 1 秒读取一次温度传感器的数据,并将数据发送到队列中。
任务 2:控制风扇
从队列中读取温度数据,如果温度超过 30°C,打开风扇;否则关闭风扇。
任务 3:上传数据
从队列中读取温度数据,并通过 Wi-Fi 上传到云端。

2、如何实现多任务?

IDF默认是集成了实时操作系统FreeRTOS的,所以FreeRTOS相关接口我们都是可以用的。

但是需要注意的是,IDF的例程中,是不会单独对FreeRTOS通用的任务创建、任务通信等RTOS相关特性进行讲解,这部分我们可以参考FreeRTOS官方文档或者IDF API文档进行了解。

IDF freertos api :https://docs.espressif.com/projects/esp-idf/zh_CN/v5.4/esp32s3/api-reference/system/freertos_idf.html

freertos 官方api:https://www.freertos.org/zh-cn-cmn-s/Documentation/02-Kernel/04-API-references/01-Task-creation/01-xTaskCreate

那这节课,我们就来了解下FreeRTOS的多任务实现。

头文件
#include "freertos/task.h"

BaseType_t xTaskCreate(
    TaskFunction_t pxTaskCode,
    const char *const pcName,
    const configSTACK_DEPTH_TYPE usStackDepth,
    void *const pvParameters,
    UBaseType_t uxPriority,
    TaskHandle_t *const pxCreatedTask
);
功能: xTaskCreate 函数用于创建一个新的 FreeRTOS 任务。该函数分配任务所需的内存,并初始化任务控制块(TCB),然后将任务添加到就绪列表中,等待调度器运行该任务。
参数:
pxTaskCode: 指向任务函数的指针。任务函数的原型必须为 void TaskFunction(void *pvParameters)。
pcName: 任务的名称,用于调试和日志记录。长度不能超过 configMAX_TASK_NAME_LEN 个字符。
usStackDepth: 任务堆栈的大小,以字为单位
pvParameters: 传递给任务函数的参数。
uxPriority: 任务的优先级。优先级值越高,任务的优先级越高。优先级值的范围通常是 0 到 configMAX_PRIORITIES - 1。
pxCreatedTask: 用于存储新创建任务的句柄。如果不需要任务句柄,可以传递 NULL。
返回值:
pdPASS: 任务创建成功。

如下方例程,我们在app_main中创建了两个任务task1和task2,创建成功后,我们可以看到app_main、task1、task2间隔运行的效果。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"

static const char *TAG = "MyModule";

static void task1_func(void *arg)
{
    while (1)
    {
        ESP_LOGI(TAG, "task1 run");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

static void task2_func(void *arg)
{
    while (1)
    {
        ESP_LOGI(TAG, "task2 run");
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void app_main(void)
{
    // 创建任务,任务堆栈大小为 2048 字,优先级为 5
    xTaskCreate(
        task1_func,    // 任务函数
        "task1_name",  // 任务名称
        2048,          // 堆栈大小(字)
        NULL,          // 传递给任务的参数
        5,             // 任务优先级
        NULL           // 任务句柄
    );
    xTaskCreate(
        task2_func,    // 任务函数
        "task2_name",  // 任务名称
        2048,          // 堆栈大小(字)
        NULL,          // 传递给任务的参数
        5,             // 任务优先级
        NULL           // 任务句柄
    );
    int cnt = 0;
    while (1)
    {
        ESP_LOGI(TAG, "app_main run: %d", cnt++);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

编译烧录后,运行效果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值