【ESP32】arduino中的ESP32实时系统FreeRTOS使用教程(一)

简单的本节略过,详细的可以看视频:单片机ESP32上的FREERTOS这个作者讲的挺好的,通俗易懂

任务的状态

FreeRTOS中的任务有运行态、就绪态、阻塞态、挂起态四种状态,在任何时候都只处于其中一种状态。任务状态之间的转换如下图所示:
在这里插入图片描述

任务的优先级

每一个任务都会有一个任务优先级,其范围为 0 (configMAX_PRIORITIES - 1),0优先级最低,(configMAX_PRIORITIES - 1)优先级最大,通常空闲任务的优先级最低,为0。

创建任务

使用动态的方法创建一个任务:


void setup() {
	xTaskCreate(task1, 		//任务函数
	            "task1",    //任务名字
	            4096,       //任务堆栈大小
		        NULL,		//传递给任务函数的参数
	            5,          //任务优先级
	            NULL);      //任务句柄
}

void task1(void *pvParameters)
{
//任务初始化程序
   while(1)
   {
   //任务的循环任务
    vTaskDelay(1);    //任务延时调度
   }
   vTaskDelete(NULL);  //删除自身函数
}

更多的任务创建和FreeRTOS函数说明看这里:
ESP32之FreeRTOS–任务的创建和运行

传递给任务函数的参数

/*
  程序: FREERTOS - 单个参数传递
        大家在看本程序的时候,需要对指针非常的了解
        知道 * -> &的作用
  作业: 添加LED3_PIN 15
  公众号:孤独的二进制
*/
byte LED1_PIN = 23;
byte LED2_PIN = 21;

void task1(void *pt) {
  byte * pbLEDPIN;
  pbLEDPIN = (byte *)pt;

  byte LEDPIN;
  LEDPIN = *pbLEDPIN;
  pinMode(LEDPIN, OUTPUT);
  while (1) {
    digitalWrite(LEDPIN, !digitalRead(LEDPIN));
    vTaskDelay(1000);
  }
}

void task2(void *pt) {
  byte LEDPIN = *(byte *)pt;
  pinMode(LEDPIN, OUTPUT);
  while (1) {
    digitalWrite(LEDPIN, !digitalRead(LEDPIN));
    vTaskDelay(3000);
  }
}

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

  byte * pbLED1PIN;
  pbLED1PIN = &LED1_PIN;

  void * pvLED1PIN;
  pvLED1PIN = (void *)pbLED1PIN;

  if (xTaskCreate(task1,
                  "Blink 23",
                  1024,
                  pvLED1PIN,
                  1,
                  NULL) == pdPASS)
    Serial.println("Task1 Created.");

  if (xTaskCreate(task2,
                  "Blink 21",
                  1024,
                  (void *)&LED2_PIN,
                  1,
                  NULL) == pdPASS)
    Serial.println("Task2 Created.");

}

void loop() {
}

程序出处
该程序task1创建一个字节指针 byte * pbLED1PIN,通过 pbLED1PIN =&LED1_PIN来指向LED1_PIN的地址,再创建pvLED1PIN这个void类型的指针来存储pbLED1PIN转换成void的值。

函数传递的是void类型的指针,所以参数需要转换成void类型的指针才能在任务函数传递。

task2则简单粗暴一点,(void *)&LED2_PIN,直接取地址,然后用空指针去指向,也一样完成传递。

结构体多参数传递

程序出处


typedef struct {
  byte pin;
  int delayTime;
} LEDFLASH;

LEDFLASH led1, led2;

if (xTaskCreate(ledFlash,
                  "FLASH LED",
                  1024,
                  (void *)&led1,
                  1,
                  NULL) == pdPASS)
    Serial.println("led1 flash task Created.");
    
void ledFlash(void *pt) {
  LEDFLASH * ptLedFlash = (LEDFLASH *)pt;
  byte pin = ptLedFlash->pin;
  int delayTime = ptLedFlash->delayTime;

  pinMode(pin,OUTPUT);
  while (1) {
    digitalWrite(pin, !digitalRead(pin));
    vTaskDelay(delayTime);
  }
}

实例化结构体led1,然后传入结构体的指针地址,再创建结构体指针(类型为LEDFLASH )使其等于pt(类型转换为LEDFLASH *),这样子就可以获取到结构体led1的地址了。

互斥量Mutex

程序
多个任务一起用同一个变量就会出问题了,所以就要引入互斥量的概念,简单来说,就是互斥锁锁住一个变量之后,只有等这个锁解了,其他任务才能使用这个变量。

/*
  程序: Tasks之间数据传递
        有多任务同时写入,或者数据大小超过cpu内存通道时,或者对共享资源的访问时候,需要有防范机制
        使用MUTEX对数据对Cirtical Section的内容进行保护
        可以想象成MUTEX就是一把锁

  公众号:孤独的二进制

  语法:
  SemaphoreHandle_t xHandler; 创建Handler
  xHandler = xSemaphoreCreateMutex(); 创建一个MUTEX 返回NULL,或者handler
  xSemaphoreGive(xHandler); 释放
  xSemaphoreTake(xHanlder, timeout); 指定时间内获取信号量 返回pdPASS, 或者pdFAIL

  理解方法:
  MUTEX的工作原理可以想象成
  共享的资源被锁在了一个箱子里,只有一把钥匙,有钥匙的任务才能对改资源进行访问
*/
SemaphoreHandle_t xMutexInventory = NULL; //创建信号量Handler

void retailTask(void *pvParam) {
  while (1) {

    // 在timeout的时间内如果能够获取就继续
    // 通俗一些:获取钥匙
    if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
      //被MUTEX保护的内容叫做 Critical Section

      for (int i; i < random(10, 100); i++) 
      vTaskDelay(pdMS_TO_TICKS(i));

        //释放钥匙
        xSemaphoreGive(xMutexInventory);
      } else {
        //无法获取钥匙
      }


    };

    vTaskDelay(100); //老板要求慢一些,客户升级后,可以再加快速度
  }
}
  if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS)
   如果没有获取到互斥量,则执行以下内容,超时时间是timeOut
        xSemaphoreGive(xMutexInventory);

ESP32的双核心

在这里插入图片描述
ESP32是具有两个核心的芯片(可以对应一下你手中的型号作对比),是一个40nm的芯片。

核心0主要负责WiFi和蓝牙,如果不是操作这两个,十分不建议将代码放在核心0中运行

/*
  程序: 多核多任务

  API:
      xPortGetCoreID() 获取当前任务运行的核心
      xTaskCreate() 有系统选择运行核心,优先选择0
      xTaskCreatePinnedToCore() 指派任何给指定核心

  公众号:孤独的二进制
*/

void taskA(void *ptParam) {
  while (1) {
    Serial.println(xPortGetCoreID());	//获取当前任务在哪个核心运行
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  xTaskCreatePinnedToCore(taskA, "Task A", 1024 * 4, NULL, 1, NULL,1);
  

}

void loop() {

Serial.println(xPortGetCoreID());

}

主要是这一句,修改最后一个参数0或1即可修改核心数,使用Arduino环境对esp进行开发时建议使用Application CPU(id=1),否则可能有bug,不建议使用xTaskCreate

  xTaskCreatePinnedToCore(taskA, "Task A", 1024 * 4, NULL, 1, NULL,1);

固定频率运行任务

以固定频率运行任务,不多也不少


  TickType_t xLastWakeTime = xTaskGetTickCount();

    vTaskDelayUntil(&xLastWakeTime, xFrequency);
    vTaskDelayUntil(上一次唤醒的时间的结构体地址, 下一次运行的时间);

软件定时器

FreeRTOS中只要内存允许,想要多少个Timer 就有多少个Timer

  lockHandle = xTimerCreate("Lock Car",
                            2000,		//两秒钟唤醒一次
                            pdFALSE,
                            (void *)0,
                            lockCarCallback);

搭建ESP32 ArduinoFreeRTOS环境可以按照以下步骤进行: 1. **安装Arduino IDE**: 首先,确保你已经安装了最新版本的Arduino IDE。如果没有安装,可以从[Arduino官网](https://www.arduino.cc/en/software)下载并安装。 2. **安装ESP32开发板支持**: 打开Arduino IDE,进入`文件` -> `首选项`,在`附加开发板管理器网址`中添加以下URL: ``` https://dl.espressif.com/dl/package_esp32_index.json ``` 然后,点击`工具` -> `开发板` -> `开发板管理器`,搜索`ESP32`并安装。 3. **选择ESP32开发板**: 安装完成后,在`工具` -> `开发板`中选择你的ESP32开发板型号,例如`ESP32 Dev Module`。 4. **安装FreeRTOS库**: Arduino IDE已经内置了对FreeRTOS的支持,你不需要额外安装库。只需在代码中包含`FreeRTOS.h`头文件即可。 5. **编写FreeRTOS代码**: 下面是个简单的示例代码,展示了如何在ESP32使用FreeRTOS创建任务: ```cpp #include <Arduino.h> #include <FreeRTOS.h> #include <task.h> void vTask1(void *pvParameters) { for (;;) { Serial.println("Task 1 is running"); vTaskDelay(pdMS_TO_TICKS(1000)); } } void vTask2(void *pvParameters) { for (;;) { Serial.println("Task 2 is running"); vTaskDelay(pdMS_TO_TICKS(1000)); } } void setup() { Serial.begin(115200); xTaskCreate(vTask1, "Task 1", 2048, NULL, 1, NULL); xTaskCreate(vTask2, "Task 2", 2048, NULL, 1, NULL); } void loop() { // 不需要在这里编写代码 } ``` 6. **上传代码**: 将ESP32开发板连接到电脑,选择正确的端口,然后点击`上传`按钮将代码上传到开发板。 7. **查看串口输出**: 打开Arduino IDE的串口监视器,设置波特率为115200,你应该会看到两个任务交替输出的信息。 通过以上步骤,你就可以在ESP32上成功搭建并运行FreeRTOS环境了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

创客阿蛋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值