FreeRTOS中文数据手册:https://www.freertos.org/zh-cn-cmn-s/RTOS.html
任务函数 | 描述 |
---|---|
xTaskCreate() | 使用动态的方法创建一个任务 |
xTaskCreateStatic() | 使用静态的方法创建一个任务 |
xTaskCreatePinnedToCore | 指定任务运行的核心(最后一个参数) |
vTaskDelete() | 删除一个任务 |
vTaskDelete(NULL) | 不创建任务句柄,表示删除当前任务 |
BaseType_t xTaskCreate(TaskFunction_t pxTaskCode, // 函数指针, 任务函数
const char *const pcName, // 任务的名字
const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小
void *const pvParameters, // 调用任务函数时传入的参数
UBaseType_t uxPriority, // 优先级
TaskHandle_t *const pxCreatedTask); // 任务句柄, 以后使用它来操作这个任务
任务的句柄,相当于任务的地址,可用通过获取任务的句柄,对任务进行设置。
#include
TaskHandle_t myHandle = NULL; // 创建一个任务句柄,空指针,避免产生野指针
void mytask(void *pt) // 不指定传入指针的类型
{
while (1)
{
Serial.println("hello world");
vTaskDelay(1000);
}
}
void setup()
{
xTaskCreate(mytask, "", 1024, NULL, 1, &myHandle);
vTaskDelay(1000);
if (myHandle != NULL)
{
vTaskDelete(myHandle); // 任务被删除后就不会在执行了,可以用于删除setup这个任务
}
}
void loop()
{
}
#include
int testnum = 1;
void mytask(void *pt)
{
int *pint = (int *)pt; // 数据解耦
Serial.println(*pint); // 输出结果为1
vTaskDelete(NULL);
}
void setup()
{
Serial.begin(9600);
xTaskCreate(mytask, "", 1024, (void *)&testnum, 1, NULL);
}
void loop()
{
}
#include
int array[] = {1, 2, 3};
void mytask(void *pt)
{
int *parray = (int *)pt; // 强制转换为数组指针
for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
Serial.println(*(parray + i)); // 输出结果:1 2 3
}
vTaskDelete(NULL);
}
void setup()
{
Serial.begin(9600);
// 数组名为数组元素的首地址,所以不需要&
xTaskCreate(mytask, "", 1024 * 2, (void *)array, 1, NULL);
}
void loop()
{
}
#include
typedef struct STRUCT
{
int a;
char b;
} myStruct;
myStruct test = {2, 'a'};
void mytask(void *pt)
{
myStruct *mytest = (myStruct *)pt; // 强制转换为结构体指针
Serial.println(mytest->a); // 输出2
Serial.println(mytest->b); // 输出a
vTaskDelete(NULL);
}
void setup()
{
Serial.begin(9600);
xTaskCreate(mytask, "", 1024, (void *)&test, 1, NULL);
}
void loop()
{
}
#include
static const char *str = "hello world"; // static修饰代表只能在本文件中使用
void mytask(void *pt)
{
char *pstr = (char *)pt; // 强制转换为字符指针
Serial.println(pstr);
vTaskDelete(NULL);
}
void setup()
{
Serial.begin(115200);
xTaskCreate(mytask, "", 1024, (void *)&str, 1, NULL);
}
void loop()
{
}
一共有25个优先级别,最低为0,最高为24。(可用修改优先级别的数目超过25,但是不建议,级别越高,越占内存)
/*获取任务优先级、修改任务优先级*/
UBaseType_t priority = 0; // 任务优先级变量
TaskHandle_t pxtask = NULL; // 创建任务的句柄
xTaskCreatePinnedToCore(task1, "", 1024 * 2, NULL, 1, &pxtask, 1);
priority = uxTaskPriorityGet(pxtask); // 查看任务的优先级
vTaskPrioritySet(pxtask, 3); // 设置任务的优先级
// 这种方法,设置优先级不起作用
xTaskCreate(task1, "", 1024 * 2, NULL, 1, NULL);
xTaskCreate(task2, "", 1024 * 2, NULL, 2, NULL);
xTaskCreatePinnedToCore(task1, "", 1024 * 2, NULL, 1, NULL, 1);
xTaskCreatePinnedToCore(task2, "", 1024 * 2, NULL, 2, NULL, 1);
使用ESP32测试注意事项:
任务的状态:running、ready、blocked、suspended(挂起,暂停)
/*任务挂起*/
TaskHandle_t pxtask = NULL; // 创建任务的句柄
xTaskCreatePinnedToCore(task1, "", 1024 * 2, NULL, 1, &pxtask, 1);
vTaskSuspend(pxtask); // 挂起任务,任务不再执行
vTaskResume(pxtask); // 恢复被挂起的任务,继续执行
vTaskSuspendAll(); // 挂起所有函数,挂起后不可以执行
vTaskResumeAll(); // 恢复所有挂起函数
vTaskList()
uxTaskGetStackHighWaterMark(句柄)
查看当前函数剩余的内存大小,如果分配的内存不够,程序虽然不会报错,但是开发板会不断地重启。
分配的数量每+1,内存+4byte
以word为单位,1word = 4bytes
TaskHandle_t taskHandle; // 计算task的空间大小
xTaskCreatePinnedToCore(task1, "", 1024 * 2, NULL, 1, &taskHandle;, 1);
int waterMark = uxTaskGetStackHighWaterMark(taskHandle);
Serial.print(F("Task Free Memory: ")); // 任务剩余空间
Serial.print(waterMark); // 返回值即是当前任务所剩栈空间的最小值
esp_task_wdt_add(句柄)
开启看门狗esp_task_wdt_reset(句柄)
喂狗