完整代码
int num = 0; // loop 函数运行次数
TaskHandle_t xHandle1 = NULL; // 第一个任务句柄
TaskHandle_t xHandle2 = NULL; // 第二个任务句柄
void setup() {
// 打开串口输出
Serial.begin(115200);
delay(100);
// 获取当前未分配的内存堆大小:
Serial.println("当前未分配的内存堆大小 =============================");
Serial.println(xPortGetFreeHeapSize());
BaseType_t xReturned1; // 第二个任务返回值
BaseType_t xReturned2; // 第一个任务返回值
// 声明需要传递的参数
char * char1 ="这是第一个任务"; // 传到第一个任务
char * char2 ="这是第二个任务"; // 传到第二个任务
// 创建第一个任务不固定任何核心
xReturned1 = xTaskCreate(
vTask, // pvTaskCode
"vTask1", // pcName
10000, // usStackDepth
(void*) char1, // pvParameters
1, // uxPriority
&xHandle1 // pvCreatedTask
);
// 打印第一个任务创建状态
Serial.println("第一个任务返回值 =============================");
Serial.println(xReturned1);
// 获取当前未分配的内存堆大小:
Serial.println("当前未分配的内存堆大小 =============================");
Serial.println(xPortGetFreeHeapSize());
// 创建第二个任务固定到核心一
xReturned2 = xTaskCreatePinnedToCore(
vTask, // pvTaskCode
"vTask2", // pcName
8192, // usStackDepth
(void*) char2, // pvParameters
1, // uxPriority
NULL, // pvCreatedTask
1 // xCoreID
);
// 打印第二个任务创建状态
Serial.println("第二个任务返回值 =============================");
Serial.println(xReturned2);
// 获取当前未分配的内存堆大小:
Serial.println("当前未分配的内存堆大小 =============================");
Serial.println(xPortGetFreeHeapSize());
}
void loop() {
Serial.println("loop 函数运行次数: " + String(num));
// 获取当前未分配的内存堆大小
Serial.println("当前未分配的内存堆大小 =============================");
Serial.println(xPortGetFreeHeapSize());
if (num > 5) {
if (xHandle1 != NULL) {
// 从外部结束第一个任务
Serial.println("从外部结束第一个任务 =============================");
vTaskDelete(xHandle1);
xHandle1 = NULL;
}
}
num++;
delay(2000);
}
// 任务函数
void vTask(void *pvParameters) {
while(true) {
// 将 pvParameters 参数转换回 char*
char *pcTaskName = (char*)pvParameters;
String st1 = pcTaskName;
Serial.println("当前任务传递的参数为 =============================> " + st1);
if (pcTaskName=="fghij" && num > 10) {
Serial.println("从内部销毁第二个任务");
// 从任务自身代码内部进行任务销毁
vTaskDelete(NULL);
}
delay(1000);
}
}
参数说明:xTaskCreate 其实内部调用的就是 xTaskCreatePinnedToCore, 只不过将 xTaskCreatePinnedToCore 第七个参数设置为 tskNO_AFFINITY, 不指定核心
pvTaskCode:
指向任务输入功能的指针。必须实现任务以永不返回(即连续循环)。
pcName:
任务的描述性名称。这主要用于方便调试。由configMAX_TASK_NAME_LEN定义的最大长度 - 默认值为16。
usStackDepth:
任务堆栈的大小指定为堆栈可以容纳的变量数 - 而不是字节数。例如,如果堆栈为16位宽且usStackDepth定义为100,则将为堆栈存储分配200个字节。
pvParameters:
指针将用作正在创建的任务的参数(下面有说明)。
uxPriority:
任务应运行的优先级。包含MPU支持的系统可以选择通过设置优先级参数的位portPRIVILEGE_BIT以特权(系统)模式创建任务。例如,要以优先级2创建特权任务,应将uxPriority参数设置为(2 | portPRIVILEGE_BIT)。
pvCreatedTask:
用于传回一个句柄,通过该句柄可以引用创建的任务(在外部通过句柄关闭该任务等)。
xCoreID:
如果值 为tskNO_AFFINITY,则创建的任务不会固定到任何CPU,并且调度程序可以在任何可用的核心上运行它。其他值表示任务应固定到的CPU的索引号。比如你的 esp32 是双核心,那么你可以指定 0, 1 这两个核心。
pvParameters说明
pvParameters 是向任务传递的参数,任务里面可以接收使用,只不过传输之前需要
1. 声明变量
2. 转成 (void*) ===> (表示任意类型的指针,或者该指针与一地址值相关,但是不清楚在此地址上的对象的类型)
3. 任务接收后再转回原来的类型
char 例子
char *char1 ="abcde";
(void*)char1
char *pcTaskName = (char*)pvParameters;
int 例子
int int1 = 12345;
(void*)int1
int pcTaskName = (int)pvParameters;
string 例子
String string1 ="abcdef";
(void*)&string1
String pcTaskName = *(String*)pvParameters;
string[] 例子
String str3[3] = {"to", "ta", "bo"};
(void*)&st3
String pcTaskName[3] = {*(String*)pvParameters, *((String*)pvParameters+1), *((String*)pvParameters+2)};