3. UART 通信与日志输出

任务目标

在 ESP32-S3 上配置 UART0(默认调试串口)与 UART1(扩展串口),实现:通过 USB 转串口与 PC 通信,输出格式化日志;PC 发送 on/off 命令控制板载 LED 开关。日志与命令复用同一 UART 通道,无需额外硬件。

硬件与环境

  • 硬件:ESP32-S3-DevKitC-1 开发板(板载 USB 转 UART,连接 UART0)
  • 依赖:ESP-IDF v5.x(需已配置好 ESP32-S3 编译环境)
  • LED:开发板板载 RGB LED 中的蓝色通道(GPIO8,低电平点亮)

完整代码

创建项目后,替换 main/uart_led_example.c 文件内容:

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_log.h"

#define LED_GPIO        8
#define UART_PORT       UART_NUM_0      // 复用默认调试串口
#define UART_TX_PIN     GPIO_NUM_43
#define UART_RX_PIN     GPIO_NUM_44
#define BUF_SIZE        1024

static const char *TAG = "uart_demo";

// 初始化 UART0,波特率 115200,8N1
static void uart_init(void) {
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };
    ESP_ERROR_CHECK(uart_driver_install(UART_PORT, BUF_SIZE * 2, 0, 0, NULL, 0));
    ESP_ERROR_CHECK(uart_param_config(UART_PORT, &uart_config));
    ESP_ERROR_CHECK(uart_set_pin(UART_PORT, UART_TX_PIN, UART_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
}

// 解析命令并控制 LED
static void process_command(char *cmd) {
    // 去除末尾换行/回车
    cmd[strcspn(cmd, "\r\n")] = '\0';
    if (strcmp(cmd, "on") == 0) {
        gpio_set_level(LED_GPIO, 0);   // 低电平点亮
        ESP_LOGI(TAG, "LED ON");
    } else if (strcmp(cmd, "off") == 0) {
        gpio_set_level(LED_GPIO, 1);   // 高电平熄灭
        ESP_LOGI(TAG, "LED OFF");
    } else {
        ESP_LOGW(TAG, "Unknown command: '%s' (expect 'on' or 'off')", cmd);
    }
}

void app_main(void) {
    // 配置 LED GPIO
    gpio_reset_pin(LED_GPIO);
    gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_level(LED_GPIO, 1);       // 初始熄灭

    uart_init();
    ESP_LOGI(TAG, "UART ready. Send 'on' or 'off' to control LED.");

    uint8_t *data = malloc(BUF_SIZE);
    while (1) {
        int len = uart_read_bytes(UART_PORT, data, BUF_SIZE - 1, pdMS_TO_TICKS(100));
        if (len > 0) {
            data[len] = '\0';
            process_command((char *)data);
        }
    }
    free(data);
}

编译与烧录

idf.py set-target esp32s3
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor    # 端口按实际修改

验证方法

  1. 烧录后,串口监视器应输出 UART ready... 日志,表明 UART 初始化成功。
  2. 在串口监视器中输入 on 并回车,观察板载蓝色 LED 点亮,同时日志输出 LED ON。
  3. 输入 off 回车,LED 熄灭,日志输出 LED OFF。
  4. 输入任意其他字符串(如 test),日志输出警告 Unknown command,LED 状态不变。

通过标准:上述 4 步行为与描述完全一致,且系统无崩溃或看门狗复位。

关键说明

  • 本示例复用 UART0(即 IDF 默认日志输出通道),因此 ESP_LOGI 与用户命令收发共用同一物理串口,无需额外接线。
  • 若使用其他开发板导致 LED 引脚不同,修改 LED_GPIO 宏即可;若板载 LED 为高电平点亮,需反转 gpio_set_level 参数。
  • 命令解析采用简单字符串匹配,未做超时或粘包处理,适用于手动输入场景;实际产品需增加帧协议与校验。