【ESP32】arduino中的ESP32实时系统FreeRTOS使用教程(一)
ESP32 FreeRTOS
- 任务的状态
- 任务的优先级
- 创建任务
- 传递给任务函数的参数
- 结构体多参数传递
- 互斥量Mutex
- ESP32的双核心
- 固定频率运行任务
- 软件定时器
简单的本节略过,详细的可以看视频:单片机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; 创建HandlerxHandler = xSemaphoreCreateMutex(); 创建一个MUTEX 返回NULL,或者handlerxSemaphoreGive(xHandler); 释放xSemaphoreTake(xHanlder, timeout); 指定时间内获取信号量 返回pdPASS, 或者pdFAIL理解方法:MUTEX的工作原理可以想象成共享的资源被锁在了一个箱子里,只有一把钥匙,有钥匙的任务才能对改资源进行访问
*/
SemaphoreHandle_t xMutexInventory = NULL; //创建信号量Handlervoid retailTask(void *pvParam) {while (1) {// 在timeout的时间内如果能够获取就继续// 通俗一些:获取钥匙if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {//被MUTEX保护的内容叫做 Critical Sectionfor (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() 有系统选择运行核心,优先选择0xTaskCreatePinnedToCore() 指派任何给指定核心公众号:孤独的二进制
*/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】arduino中的ESP32实时系统FreeRTOS使用教程(一)相关推荐
- Esp32 C3 Arduino 串口开发(6)-使用SDK在Arduino中开发
直接使用 IDFV4.33的SDK直接在Arduino中开发,以下代码测试成功.通过FreeRTOS创建多任务,RX和TX分别在两个任务中互不影响.同时测试了ESP_LOG相关函数和设置 代码如下. ...
- 服务器.esp文件,ESP32 Arduino教程:通过软接入点(soft AP)实现HTTP服务器-esp文件
在本ESP32(http://www.dfrobot.com.cn/goods-1359.html)教程中,我们将检查如何设置一个异步HTTP web服务器,该设备作为软访问点运行. 本ESP32教程 ...
- 彩屏显示入门:我要五彩斑斓的黑 | 用Arduino玩转ESP32与掌控板系列
众所周知,掌控板在创客教育中用的非常广泛,它是一块基于 ESP32 的学习开发板.大家对掌控板编程,用的比较多的都是图形化编程的方式,比如 mPython.Mind+ 等.但是,既然掌控板是基于 ES ...
- Arduino手动添加ESP32相关开发板(图文并茂)
一.前述 使用Arduino开发ESP32,就绕不开添加ESP32开发板这一步,网上有很多相关教程,介绍的很详细,但是在实际操作过程中还是遇到一些问题,所以在这里记录一下,希望可以帮到别人. ...
- Arduino开发板esp32
1:Arduino IDE下载地址 https://www.arduino.cc/en/Main/Software?setlang=cn 2:安装打开 其中setup()用来初始化变量.调用数据库.脚 ...
- 在Arduino上搭建ESP32开发环境
ESP32开发板可以通过官方的工具链.编译工具.ESP-IDF配合文本编辑器进行编程,但这样的方式有时比较麻烦,而且对新手极其不友好,因此经过简单配置,可使用Arduino对ESP32开发板进行编程. ...
- ESP32+arduino智能浇水系统
一.ESP32+arduino智能浇水系统 随着人类居住条件的改善及对生态生活环境的关注,花卉养殖得到社会和人类个体的重视.这些具有生命特征的植物需 要科学合理的人工照顾.本研究提出了利用ESP WR ...
- Arduino : 在 ESP32 上使用 LEDC (PWM) (3)
文章目录 目的 配套介绍 主要函数 使用示例 总结 Arduino core for the ESP32 并没有一般 Arduino 中用来输出 PWM 的 analogWrite(pin, valu ...
- 使用Arduino IDE的ESP32电容式触摸传感器引脚
本文介绍了如何在Arduino IDE中使用ESP32触摸针. ESP32触摸引脚可以感应任何保持电荷的变化.它们通常用于将ESP32从深度睡眠中唤醒. ESP32触控感应器介绍 touchRead( ...
最新文章
- java jdk 环境变量配置(window 10 系统)
- POJ 1236 Network of Schools(tarjan)
- 网站安全--又一种防盗链的措施!
- HLG 1349 Graph [floyed]
- 浏览器如何渲染页面?
- 中国研制600公里时速磁悬浮:北京到上海,仅需3.5小时左右
- 哪个牌子的平板电脑好_重庆智能会议平板哪个牌子好?软硬件好才是真的好!...
- java实现原数组根据下标分隔成两个子数组并且在原数组中交换两个子数组的位置...
- Linux : shell基础(慕课网Linux达人养成计划课程笔记)
- cos7安装mysql_centos7 安装 mysql
- Android Studio(十):添加assets目录
- 计算机辅助教学:多媒体课件制作教程,多媒体课件制作5步曲!
- PHP 使用 hprose RPC 服务 系列文章之三——Laravel5.8中使用Hprose
- Excel中输入身份证号后三位变成0的情况处理如下
- php原生检测用户,php代码在线测试_php检测用户在线状态的实例代码
- hourglass论文_论文笔记 Stacked Hourglass Networks for Human Pose Estimation
- 中文名字和英文名字正则匹配
- 堆叠柱状图加上折线图-echart图表(一)
- 高等数学基础概念的Python开发实现
- “AI安全”风起云涌,拿下A轮融资的瑞莱智慧如何与群雄共舞?