ESP32学习笔记(四)——FreeRTOS多任务
注:使用VSCode中的ESP-IDF插件进行开发,笔记基于B站UP主艾谷科技的视频教程。
注:使用VSCode中的ESP-IDF插件进行开发,笔记基于B站UP主艾谷科技的视频教程
ESP32S3+ESPIDF入门教程 程序纯手打 手把手教学 中文字幕 持续更新中_哔哩哔哩_bilibili
目录
1.复制上一小节的4_Key文件并重命名为5_Multitask
一、 项目要求

直接运行会导致卡顿,需要引入FreeRTOS多任务系统
二、项目工程
1.复制上一小节的4_Key文件并重命名为5_Multitask
2.修改文件
1.修改key.c文件
#include "key.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
void key_init(void)
{
gpio_config_t gpio_cfg = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = (1ull << GPIO_NUM_9), //仅初始化GPIO9,IO9外接一个按键
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.pull_up_en = GPIO_PULLUP_ENABLE,
};
gpio_config (&gpio_cfg);
}
uint8_t key_scan(void)
{
uint8_t key_num =0;
if(gpio_get_level(GPIO_NUM_9) == 0)
{
vTaskDelay(20);
while (gpio_get_level(GPIO_NUM_9) == 0);
vTaskDelay(20);
key_num = 1;
}
return key_num ;
}
2.修改led.c文件
#include "led.h"
#include "driver/gpio.h"
void led_init(void)
{
esp_err_t err;
gpio_config_t gpio_cfg = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT_OUTPUT,
//初始化两个GPIO引脚,分别在IO38,GO39连接LED
.pin_bit_mask = (1ull << GPIO_NUM_38)|(1ull << GPIO_NUM_39),
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.pull_up_en = GPIO_PULLUP_ENABLE,
};
err = gpio_config (&gpio_cfg);
if(err != ESP_OK)
{
printf("gpio init error!\r\n");
}
gpio_set_level(GPIO_NUM_38, 1);
gpio_set_level(GPIO_NUM_39, 1);
}
void gpio_toggle(gpio_num_t gpio_num)
{
if(gpio_get_level(gpio_num) == 0)
{
gpio_set_level(gpio_num, 1);
}
else
{
gpio_set_level(gpio_num, 0);
}
}
3.修改main.c文件
分别建立两个任务函数,任务函数的编写参数是void *param,任务函数必须是无限循环,在函数xTaskCreatePinnedToCore的原始函数中的第一个入口参数,跳转后可以看到任务函数的原型。使用任务函数的时候必须在函数内部加入延时,才能进行后续的任务调度。
void led_task(void *param)
{
while (1)
{
gpio_toggle(GPIO_NUM_38); //LED1每隔100ms闪烁一次
vTaskDelay(100);
}
}
void key_task(void *param)
{
uint8_t key_num = 0;
while(1)
{
key_num = key_scan();
if(key_num == 1)
{
gpio_toggle(GPIO_NUM_39); //检测按键按下后改变LED2的状态
}
vTaskDelay(5);
}
}
调用xTaskCreatePinnedToCore函数使得两个任务能够运行,调用该函数时需要包含头文件
“freertos/FreeRTOS.h”、“freertos/task.h”
void app_main(void)
{
led_init();
key_init();
xTaskCreatePinnedToCore( led_task,"led_task",1024,NULL,1,NULL,0 );
xTaskCreatePinnedToCore( key_task,"key_task",1024,NULL,1,NULL,0 );
}
xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pvCreatedTask,
const BaseType_t xCoreID );
pxTaskCode:任务函数的名称;
const pcName:任务名称用于调试;
usStackDepth:任务占用的堆栈大小,此处分配1024字节;
pvParameters:给任务函数传入的值,此处不需要传入任何参数,输入NULL;
uxPriority:该任务函数的优先级,数字越大,任务优先级越高,任务越先执行;
pvCreatedTask:任务句柄,可用于管理任务(如删除、挂起、恢复)。两个任务函数都没有创建,此处填写NULL;
xCoreID:任务函数在哪一个内核中执行,ESP32有两个内核,可以填写0或1。
0:固定到 Core 0(PRO_CPU,通常处理Wi-Fi/蓝牙)。
1:固定到 Core 1(APP_CPU,通常处理用户任务)。
tskNO_AFFINITY(值为
-1):允许任务在任意核心运行(由调度器决定)。
4.编译
5.连接电路

6.下载并运行
运行结果:两个任务独立运行,互不干扰
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)