第四章:系统基础与调试
ESP32采用FreeRTOS作为其实时操作系统内核,ESP-IDF提供了原生API来创建和管理任务。
在FreeRTOS中,任务是程序执行的基本单元。每个任务都有自己的堆栈和优先级。
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void my_task(void *pvParameters) {
while(1) {
// 任务代码
vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时1秒
}
}
void app_main() {
xTaskCreate(
my_task, // 任务函数
"My Task", // 任务名称
2048, // 堆栈大小(字节)
NULL, // 参数指针
5, // 优先级(数字越大优先级越高)
NULL // 任务句柄指针
);
}
注意: ESP-IDF中的任务优先级范围是0-25,其中0是最低优先级,25是最高优先级。
可以通过任务创建时的参数指针向任务传递数据:
typedef struct {
int id;
char *name;
} task_params_t;
void parameterized_task(void *pvParameters) {
task_params_t *params = (task_params_t *)pvParameters;
ESP_LOGI("TASK", "Task %d: %s started", params->id, params->name);
// ...
}
void app_main() {
task_params_t params = {
.id = 1,
.name = "Parameterized Task"
};
xTaskCreate(parameterized_task, "Param Task", 2048, ¶ms, 5, NULL);
}
关键点: 任务堆栈大小需要根据任务需求合理设置,过小会导致堆栈溢出,过大会浪费内存。
FreeRTOS提供了多种任务管理函数:
// 删除当前任务 vTaskDelete(NULL); // 挂起任务 vTaskSuspend(task_handle); // 恢复挂起的任务 vTaskResume(task_handle); // 延时任务 vTaskDelay(ms / portTICK_PERIOD_MS); // 精确延时 vTaskDelayUntil(&last_wake_time, ms / portTICK_PERIOD_MS);
ESP-IDF提供了强大的日志系统,可以分级输出调试信息,便于开发和故障排查。
ESP-IDF日志分为5个级别:
#include "esp_log.h"
static const char *TAG = "MY_MODULE";
void some_function() {
ESP_LOGE(TAG, "This is an error message");
ESP_LOGW(TAG, "This is a warning message");
ESP_LOGI(TAG, "This is an info message");
ESP_LOGD(TAG, "This is a debug message");
ESP_LOGV(TAG, "This is a verbose message");
}
可以通过menuconfig或代码设置日志级别:
// 通过menuconfig配置:
// Component config → Log output → Default log verbosity
// 通过代码动态设置:
esp_log_level_set("MY_MODULE", ESP_LOG_INFO); // 设置特定TAG的日志级别
esp_log_level_set("*", ESP_LOG_WARN); // 设置所有TAG的日志级别
警告: 生产环境中应将日志级别设置为WARNING或ERROR,以减少不必要的输出和提高性能。
ESP-IDF还提供了一些高级日志功能:
// 带颜色的日志输出
ESP_LOG_COLOR_E(TAG, "Red error message");
ESP_LOG_COLOR_W(TAG, "Yellow warning message");
// 带时间戳的日志
ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO, TAG, "Message with local timestamp");
// 十六进制dump
uint8_t buffer[] = {0x01, 0x02, 0x03, 0x04};
ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, sizeof(buffer), ESP_LOG_INFO);
最佳实践: 为每个模块定义不同的TAG,便于日志过滤和分析。TAG名称应简洁且能明确标识模块。
扫描访问店铺
扫描添加客服