ESP32S3——多线程

2024-06-05 20:52
文章标签 多线程 esp32s3

本文主要是介绍ESP32S3——多线程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、环境:

平台:arduino IDE 或 VS Code PlatformIO 皆可。

我的是后者,具体为:

        框架:VS + PlatformIO + Arduino

二、硬件准备:

一个esp32s3

本文用到的是U0RXD(GPIO44 )与U0TXD(GPIO43)引脚

一台电脑

一根数据线

三、代码功能:

        一个LED一秒亮一次:

        另一个LED两秒两一次。

注意:ESP32S3有两个type-C口,一个UART用来下载调试程序,一个USB用来供电。下载完程序后切换到USB,现象会更明显。

四、最简代码

#include <Arduino.h>#define LED_U0RXD 44
#define LED_U0TXD 43// 创建两个任务,
// TaskBlink1任务:一个LED 1s亮一次,
// TaskBlink2任务:另一个LED 2s亮一次。
void TaskBlink1( void *pvParameters );
void TaskBlink2( void *pvParameters );void setup() {Serial.begin(115200);uint32_t blink_delay1 = 1000; // Delay between changing state on LED pinuint32_t blink_delay2 = 2000; // Delay between changing state on LED pinxTaskCreate(TaskBlink1       // 这个任务运行的函数,  "Task Blink1" //  给人看的名字,  2048        // 任务栈的大小,用于存储任务运行时的上下文信息。简单来说,就是最多存这么多信息,  (void*) &blink_delay1 // 任务参数。要么没有填NULL;要么必须为无类型指针,  2  // 优先级,  NULL // 任务的句柄,用于管理和控制任务,NULL相当于0,意味着此处不需要任务句柄);xTaskCreate(TaskBlink2       // 这个任务运行的函数,  "Task Blink2" //  给人看的名字,  2048        // 任务栈的大小,用于存储任务运行时的上下文信息。简单来说,就是最多存这么多信息,  (void*) &blink_delay2 // 任务参数。要么没有填NULL;要么必须为无类型指针,  2  // 优先级,  NULL // 任务的句柄,用于管理和控制任务,NULL相当于0,意味着此处不需要任务句柄);Serial.printf("Basic Multi Threading Arduino Example\n");// Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}void loop(){
// 这里什么都不用写
}/*---------------------- Tasks ---------------------*/void TaskBlink1(void *pvParameters){  // This is a task.uint32_t blink_delay = *((uint32_t*)pvParameters);// 初始化LED_U0RXD为output模式pinMode(LED_U0RXD, OUTPUT);
// for死循环for (;;){ // 多线程,每个任务必须是死循环digitalWrite(LED_U0RXD, HIGH);   // turn the LED on (HIGH is the voltage level)delay(blink_delay);digitalWrite(LED_U0RXD, LOW);    // turn the LED off by making the voltage LOWdelay(blink_delay);}
}void TaskBlink2(void *pvParameters){  // This is a task.uint32_t blink_delay = *((uint32_t*)pvParameters);// 初始化LED_U0RXD为output模式pinMode(LED_U0TXD, OUTPUT);for (;;){ // A Task shall never return or exit.digitalWrite(LED_U0TXD, HIGH);   // turn the LED on (HIGH is the voltage level)delay(blink_delay);digitalWrite(LED_U0TXD, LOW);    // turn the LED off by making the voltage LOWdelay(blink_delay);}
}

主要代码解析

        我们可以看到,多线程其实很简单。        

        主要就是函数 xTaskCreate( ) :创建一个线程,然后在线程内运行 TaskBlink1( ) 函数。

  • TaskBlink1 :这个任务运行的函数
  •  "Task Blink1":给人看的名字
  • 2048 :任务栈的大小,用于存储任务运行时的上下文信息。简单来说,就是最多存这么多信息
  •  (void*) &blink_delay1 :任务参数。要么没有填NULL;要么必须为无类型指针
  • 2 :优先级
  • NULL : 任务的句柄,用于管理和控制任务,NULL相当于0,意味着此处不需要任务句柄

五、多核下的多线程

        有些板子有多个核,比如:ESP32S3有两个核,本身就可以就可以让两个核单独控制一个LED,实现上文双线程的效果。所以说,对于有两个核的ESP32S3,既可以指定某一个核运行俩线程,也可以指定俩核单独运行一个线程,而实现相同的效果。

        这里介绍俩核各自运行一个线程,各自控制一个LED的闪烁。

        话不多说,上代码:

#include <Arduino.h>// #if CONFIG_FREERTOS_UNICORE
// #define ARDUINO_RUNNING_CORE 0
// #else
// #define ARDUINO_RUNNING_CORE 1
// #endif#define LED_U0RXD 44
#define LED_U0TXD 43// 创建两个任务,
// TaskBlink1任务:一个LED 1s亮一次,
// TaskBlink2任务:另一个LED 2s亮一次。
void TaskBlink1(void *pvParameters);
void TaskBlink2(void *pvParameters);void setup() {Serial.begin(115200);xTaskCreatePinnedToCore(TaskBlink1,  "TaskBlink1"   // 任务名,  1024  // This stack size can be checked & adjusted by reading the Stack Highwater,  NULL,  2  // 任务优先级, with 3 (configMAX_PRIORITIES - 1) 是最高的,0是最低的.,  NULL ,  0); // 第一个核xTaskCreatePinnedToCore(TaskBlink2,  "TaskBlink2" //任务名,  1024  // 栈大小,  NULL,  1  // 任务优先级,  NULL ,  1); // 第二个核//现在,接管单个任务调度控制的任务调度程序将自动启动。
}void loop()
{// Empty. Things are done in Tasks.
}/*---------------------- Tasks ---------------------*/void TaskBlink1(void *pvParameters){  // This is a task.uint32_t blink_delay = 1000;// 初始化LED_U0RXD为output模式pinMode(LED_U0RXD, OUTPUT);
// for死循环for (;;){ // 多线程,每个任务必须是死循环digitalWrite(LED_U0RXD, HIGH);   // turn the LED on (HIGH is the voltage level)delay(blink_delay);digitalWrite(LED_U0RXD, LOW);    // turn the LED off by making the voltage LOWdelay(blink_delay);}
}void TaskBlink2(void *pvParameters){  // This is a task.uint32_t blink_delay = 2000;// 初始化LED_U0RXD为output模式pinMode(LED_U0TXD, OUTPUT);for (;;){ // A Task shall never return or exit.digitalWrite(LED_U0TXD, HIGH);   // turn the LED on (HIGH is the voltage level)delay(blink_delay);digitalWrite(LED_U0TXD, LOW);    // turn the LED off by making the voltage LOWdelay(blink_delay);}
}

主要代码解析

        我们可以看到,多核、多线程其实也很简单。        

        主要就是函数 xTaskCreatePinnedToCore ( ) :创建一个线程,并指定哪一个核运行线程,然后在线程内运行 TaskBlink1( ) 函数。与函数 xTaskCreate( ) 相比只多了指定运行的核,这一步。 

  • TaskBlink1 :这个任务运行的函数
  •  "Task Blink1":给人看的名字
  • 2048 :任务栈的大小,用于存储任务运行时的上下文信息。简单来说,就是最多存这么多信息
  •  (void*) &blink_delay1 :任务参数。要么没有填NULL;要么必须为无类型指针
  • 2 :优先级
  • NULL : 任务的句柄,用于管理和控制任务,NULL相当于0,意味着此处不需要任务句柄
  • 0 :第一个核。只有俩核,只能填0或1

最后,我有话说:

        如果文章对你有帮助,我很开心。有疑问,请留言,看到后,我会回复。

这篇关于ESP32S3——多线程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1034154

相关文章

多线程解析报表

假如有这样一个需求,当我们需要解析一个Excel里多个sheet的数据时,可以考虑使用多线程,每个线程解析一个sheet里的数据,等到所有的sheet都解析完之后,程序需要提示解析完成。 Way1 join import java.time.LocalTime;public class Main {public static void main(String[] args) thro

Java 多线程概述

多线程技术概述   1.线程与进程 进程:内存中运行的应用程序,每个进程都拥有一个独立的内存空间。线程:是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换、并发执行,一个进程最少有一个线程,线程实际数是在进程基础之上的进一步划分,一个进程启动之后,进程之中的若干执行路径又可以划分成若干个线程 2.线程的调度 分时调度:所有线程轮流使用CPU的使用权,平均分配时间抢占式调度

Java 多线程的基本方式

Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):

JAVA- 多线程

一,多线程的概念 1.并行与并发 并行:多个任务在同一时刻在cpu 上同时执行并发:多个任务在同一时刻在cpu 上交替执行 2.进程与线程 进程:就是操作系统中正在运行的一个应用程序。所以进程也就是“正在进行的程序”。(Windows系统中,我们可以在任务管理器中看 到进程) 线程:是程序运行的基本执行单元。当操作系统执行一个程序时, 会在系统中建立一个进程,该进程必须至少建立一个线

多线程篇(阻塞队列- LinkedBlockingDeque)(持续更新迭代)

目录 一、LinkedBlockingDeque是什么 二、核心属性详解 三、核心方法详解 addFirst(E e) offerFirst(E e) putFirst(E e) removeFirst() pollFirst() takeFirst() 其他 四、总结 一、LinkedBlockingDeque是什么 首先queue是一种数据结构,一个集合中

多线程篇(阻塞队列- LinkedBlockingQueue)(持续更新迭代)

目录 一、基本概要 1. 构造函数 2. 内部成员 二、非阻塞式添加元素:add、offer方法原理 offer的实现 enqueue入队操作 signalNotEmpty唤醒 删除线程(如消费者线程) 为什么要判断if (c == 0)时才去唤醒消费线程呢? 三、阻塞式添加元素:put 方法原理 图解:put线程的阻塞过程 四、非阻塞式移除:poll方法原理 dequ

spring笔记 多线程的支持

spring的工作机制 136  属性编辑器 140 spring事件的体系结构 168 Bean间的关系 109 继承 依赖 引用     Bean的继承          1 为了简化初始化的属性注入;          2 子Bean和父Bean相同的属性值,使用子Bean的     Bean的依赖 Srping控制相互依赖的Bean之间,属性注入的顺序,防止出错  depend-on

【编程底层思考】详解Java的JUC多线程并发编程底层组件AQS的作用及原理

Java中的AbstractQueuedSynchronizer(简称AQS)是位于java.util.concurrent.locks包中的一个核心组件,用于构建锁和其他同步器。AQS为实现依赖于FIFO(先进先出)等待队列的阻塞锁和相关同步器提供了一套高效、可扩展的框架。 一、AQS的作用 统一同步状态管理:AQS提供了一个int类型的成员变量state,用于表示同步状态。子类可以根据自己

多线程的系列文章

Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1)   Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多线程学习(四)等待/通知(wait/notify)机制 Java多线程学习(五)线程间通信知识点补充 Java多线程学习(六)Lock锁的使用 Java多

多线程 线程池的创建

一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的。在jdk1.5之后这一情况有了很大的改观。Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用。为我们在开发中处理线程的问题提供了非常大的帮助。 二:线程池 线程池的作用: 线程池作用就是限制系统中执行线程的数量。