ESP32-S3串口打印需延迟才能正常输出,求解决方案
解决ESP32-S3串口调试初期打印丢失问题
问题现象
在Arduino框架开发中,使用Serial.println()输出调试信息时,ESP32-S3(如esp32-s3-devkitc-1)会出现setup()打印和loop()前几次打印丢失的情况。依赖固定delay(3500)可以解决,但希望实现像普通ESP32(如esp32doit-devkit-v1)一样的即时调试反馈。
测试代码
#include <Arduino.h> int loopCount = 0; void setup() { Serial.begin(460800); // delay(3500); while(!Serial) {} Serial.println("setup"); } void loop() { Serial.println(String(++loopCount) + " " + String(millis())); delay(1000); }
硬件表现差异
- 普通ESP32:注释掉
delay和while(!Serial)后,输出正常:setup 1 28 2 1029 3 2028 - ESP32-S3:
- 无
delay或while(!Serial)时,丢失前几次打印:4 3098 5 4098 6 5098 - 使用
while(!Serial)时,丢失更多打印:5 4098 6 5098 7 6098 8 7098
- 无
PlatformIO配置
[platformio] default_envs = esp32 src_dir = src include_dir = include [env:esp32] platform = espressif32 ; board = esp32doit-devkit-v1 board = esp32-s3-devkitc-1 framework = arduino upload_port = /dev/cu.usb* ; Serial Monitor options monitor_speed = 460800 monitor_filters = colorize monitor_echo = yes
核心原因
ESP32-S3默认的Serial是USB CDC虚拟串口,而普通ESP32的Serial为硬件UART。USB串口需要完成主机(Mac)的枚举过程才能建立通信,这段时间内ESP32-S3已经执行完setup和早期loop代码,导致打印内容丢失;while(!Serial)会让程序持续等待USB串口就绪,但PlatformIO串口监视器通常在上传完成后才打开,进一步延长等待时间,错过更多输出。
解决方法
方法1:改用硬件UART
ESP32-S3自带多个硬件UART,切换到硬件UART可避开USB枚举问题,和普通ESP32的调试逻辑一致:
void setup() { // 使用UART1,引脚TX=17、RX=16(可根据硬件引脚定义调整) Serial1.begin(460800, SERIAL_8N1, 16, 17); Serial1.println("setup"); } void loop() { Serial1.println(String(++loopCount) + " " + String(millis())); delay(1000); }
同时修改PlatformIO配置的monitor_port,指定硬件UART对应的串口设备(如/dev/cu.usbserial-*)。
方法2:优化USB CDC等待逻辑
如果坚持使用USB CDC串口,将while(!Serial)替换为等待用户输入的逻辑,灵活控制打印时机:
void setup() { Serial.begin(460800); // 等待用户打开串口监视器并按任意键 while (!Serial.available()) { delay(50); } // 清空缓冲区,避免输出用户按键内容 Serial.read(); Serial.println("setup"); }
方法3:启用早期调试输出
通过ESP-IDF的app_main入口提前初始化串口,在Arduino框架启动前就开始输出调试信息:
- 修改PlatformIO配置,添加编译选项:
[env:esp32] platform = espressif32 board = esp32-s3-devkitc-1 framework = arduino upload_port = /dev/cu.usb* build_flags = -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 monitor_speed = 460800 monitor_filters = colorize monitor_echo = yes - 修改代码,添加
app_main初始化:#include <Arduino.h> extern "C" void app_main() { Serial.begin(460800); delay(100); // 给USB枚举留短暂时间 Serial.println("app_main: early debug"); initArduino(); // 启动Arduino框架 } int loopCount = 0; void setup() { Serial.println("setup"); } void loop() { Serial.println(String(++loopCount) + " " + String(millis())); delay(1000); }
内容的提问来源于stack exchange,提问作者AndrewCSP
相关产品推荐
相关产品推荐

