记录一次从 Arduino 开发转向 ESP-IDF 的完整过程,包括 ESP32-S3 环境搭建、小智 AI 烧录、I2S 音频调试、TFT 屏幕适配以及硬件踩坑记录。
本文不是"照着官方文档抄一遍"的教程,而是一个开发者从浏览器烧录 → VS Code + ESP-IDF → 硬件调试 → 屏幕白屏排查的全过程踩坑实录。


一、背景

最近尝试使用 ESP32-S3 N16R8 开发板运行小智 AI 语音助手。

目标:

  • ESP32-S3 运行小智 AI 固件
  • 接入 I2S 麦克风
  • 接入 I2S 功放播放
  • 添加 TFT 显示屏
  • 后续扩展:
  • AI 对话
  • 实时语音通信
  • 本地音频处理
  • 音乐播放

开发环境:

  • macOS Sequoia
  • VS Code
  • ESP-IDF Extension
  • ESP32-S3 N16R8

资料来源:


二、第一次烧录:从浏览器开始

2.1 浏览器烧录流程

最开始我是跟着文档,用浏览器方式(ESP Launchpad)一步步烧录的。
整个流程很简单:
1.打开 ESP Launchpad 官网
2.选择小智 AI 固件
3.连接开发板
4.点击烧录

2.2 遇到的第一个坑:COM 端口无法连接

但最大的问题是——开发板的端口是否能被识别,直接决定连接能否成功。
我第一次连接时,页面直接报错:
在这里插入图片描述

Unable to detect device. Please ensure the device is not connected in
another application.

这个问题的排查思路:

  • 检查 USB 线是否是数据线(不是充电线)
  • 检查是否有其他程序占用了串口
  • 尝试按一下开发板的 BOOT 键再连接
  • 换一个 USB 口试试

2.3 烧录成功后的验证

烧录完成后,通过串口日志可以确认基础功能是否正常:

MQTT: Connected to endpoint
Application: Activation done
StateMachine: activating -> idle

说明:

  • ✅ WiFi 连接成功
  • ✅ MQTT 服务器连接成功
  • ✅ AI 服务激活成功
    音频模块正常时,日志会出现:
Wake word detected: 你好小智
StateMachine: idle -> listening
StateMachine: listening -> speaking

代表:

  • ✅ 麦克风采集正常
  • ✅ 唤醒模型运行正常
  • ✅ AI 回复正常

三、为什么从浏览器烧录转向 ESP-IDF?

起初我用浏览器烧录的是 bread-compact-wifi(无屏幕版),一切正常。
但问题来了——我买的显示屏模块和博主的不一样:

  • 博主的显示屏是 8 排针脚的
  • 我的是 7 个针脚的
    浏览器烧录只能用预设好的固件,没法自定义屏幕引脚和驱动。
    所以我必须放弃浏览器方式,改用 VS Code + ESP-IDF 去修改源码、重新编译烧录。

四、ESP-IDF 开发环境搭建

4.1 VS Code 插件安装

在 VS Code 插件市场搜索并安装:

  • ESP-IDF Extension(Espressif 官方)—— 负责编译、烧录、串口监控、menuconfig 配置、调试
  • C/C++ Extension(Microsoft)—— 语法支持

4.2 底部快捷工具栏说明

VS Code 状态栏最下方的图标含义如下:
在这里插入图片描述

4.3 核心 Command Palette 快捷命令

按 Cmd + Shift + P(Mac)或 Ctrl + Shift + P(Windows)调出命令面板:

  • ESP-IDF: Full Clean — 清理所有临时编译文件(修改 sdkconfig 或 .h 头文件未生效时必做)
  • ESP-IDF: SDK Configuration Editor (GUI) — 打开可视化 kconfig 设置页面
  • ESP-IDF: Select Flash Method and Port — 选择串口和烧录模式(通常选 UART)

4.4 setting.json 优化配置

建议在 settings.json 中加上:

{
  "df.flashType": "UART",
  "df.flashBaudRate": "921600"
}

提高烧录速度,避免每次烧录等半天。


五、ESP32-S3 N16R8 硬件注意事项

5.1 🚨 致命避坑:PSRAM GPIO 冲突

我的开发板:ESP32-S3 N16R8
带:

  • 16MB Flash
  • 8MB Octal PSRAM

⚠️ 重要修正:网上很多文章说"GPIO 47 在 N16R8 芯片内部被八路高速内存(PSRAM)总线占用",这个描述不够准确。
更准确的说法是:ESP32-S3 N16R8 使用 Octal PSRAM 时,部分 GPIO 会被 Flash/PSRAM
总线占用,不能作为普通外设 IO 使用。实际可用 GPIO 需要结合芯片封装和官方 datasheet 判断。 不同 ESP32-S3
模组封装可能不同,不要一概而论。

踩坑经历:
最开始我把 TFT 的 SDA/MOSI 接到了 GPIO 47,结果:

  • ❌ 屏幕白屏
  • ❌ SPI 完全无法通信

原因: GPIO 47 被 PSRAM 总线占用,系统启动 PSRAM 后该引脚会被锁死。
解决方案: 将 SDA/MOSI 挪至空闲管脚 GPIO 1(或 GPIO 11 / 12 等)。


六、I2S 音频模块接线

6.1 麦克风模块

小智默认配置:

#define AUDIO_I2S_MIC_GPIO_WS  GPIO_NUM_4
#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5
#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6

实际接线:
在这里插入图片描述
验证方法:
日志中出现:

AFE Pipeline:
[input] -> VAD -> WakeNet

表示录音链路正常。

6.2 播放模块

小智默认:

#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7
#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15
#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16

实际连接:
在这里插入图片描述
真实踩坑过程:

第一次烧录完成后:

  • ✅ WiFi 正常
  • ✅ MQTT 正常
  • ✅ AI 文字回复正常
  • ✅ 麦克风唤醒正常
  • ❌ 但是没有声音! 排查了半天,最后发现是 播放 I2S GPIO 不匹配。 修改后:
  • DIN → GPIO 7
  • BCLK → GPIO 15
  • LRC → GPIO 16 重新烧录,AI 语音播放恢复正常 🎉

经验总结: 如果 AI 文字回复正常但没有声音,优先检查 I2S 播放 GPIO 是否匹配。


七、2.8 寸 SPI TFT 屏适配

7.1 关于屏幕驱动型号的判断

我的屏幕:7 针 SPI TFT
引脚:CS、DC、RST、SDA、SCK、VCC、GND

⚠️ 注意:购买页面显示"2.8 寸 SPI TFT",并不能直接确定驱动型号。 常见的 2.8 寸屏驱动有:

  • ILI9341(最常见,240×320)
  • ST7789(也很常见,240×320,IPS 屏常用)
  • ILI9488(320×480,分辨率更高) 这几种外观非常接近,可以提前调研看看博主们用的什么,这些都能查到, 别跟我似的瞎猫碰上死耗子,瞎买一通最后显示屏跟博主不一样最后还得修源码烧录进去

我这边最终确认是 ILI9341。

7.2 接线表

在这里插入图片描述

💡 注意:这里的 SDA 不是 I2C 的 SDA,而是 SPI 的 MOSI。


八、小智 AI 项目工程配置与板型切换

8.1 sdkconfig 配置文件修改

项目默认开启的是"无屏 Wi-Fi 版",需手动开启"LCD 带屏版":
打开项目根目录下的 sdkconfig,找到 CONFIG_BOARD_TYPE 区域,修改为:

# CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI is not set
CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_LCD=y

8.2 配置文件修改(bread-compact-wifi-lcd/config.h)

打开 main/boards/bread-compact-wifi-lcd/config.h,更新 SPI 引脚和驱动预设:

// 引脚定义(避开 PSRAM 47号管脚)
#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC   // 7脚屏背光板载硬连VCC,填 NC
#define DISPLAY_MOSI_PIN      GPIO_NUM_1    // SDA / MOSI 改为 GPIO 1
#define DISPLAY_CLK_PIN       GPIO_NUM_21   // SCL / CLK
#define DISPLAY_DC_PIN        GPIO_NUM_40   // DC / RS
#define DISPLAY_RST_PIN       GPIO_NUM_45   // RES / RST
#define DISPLAY_CS_PIN        GPIO_NUM_41   // CS

// 保底屏幕驱动配置(如 SDK 未选中宏,默认按 2.8寸 ILI9341 驱动加载)
#if !defined(CONFIG_LCD_ST7789_240X320) && !defined(CONFIG_LCD_ST7789_240X320_NO_IPS) && \
    !defined(CONFIG_LCD_ILI9341_240X320) && !defined(CONFIG_LCD_ILI9341_240X320_NO_IPS) && \
    !defined(CONFIG_LCD_GC9A01_240X240)  && !defined(CONFIG_LCD_CUSTOM)
#define CONFIG_LCD_ILI9341_240X320_NO_IPS
#endif

8.3 修改后必须清理缓存!
ESP-IDF 使用 CMake 缓存机制。
修改过以下内容后:

  • sdkconfig
  • GPIO 定义
  • board config
  • CMakeLists.txt
    必须执行:
ESP-IDF: Full Clean

然后再:

Build → Flash → Monitor

否则可能继续使用旧配置,改了半天没效果,怀疑人生。


九、白屏故障快速排查 CheckList

如果烧录后屏幕仍然白屏,请按以下流程速查:

第一步:查日志板型

打开 VS Code 串口 Monitor,按复位键查看开机日志:

  • 必须看到 bread-compact-wifi-lcd
  • 如果仍显示 bread-compact-wifi,说明 sdkconfig 没修改成功或缓存未清理

第二步:查 PSRAM 管脚

确认 MOSI 线没有接到以下管脚上:

  • GPIO 47 / 48
  • GPIO 35-37(部分模组也可能被占用)

第三步:彻底清理缓存

修改过 sdkconfig 或 CMakeLists.txt 后,必须执行 ESP-IDF: Full Clean(或手动删除项目下的 build 文件夹),再重新编译烧录。

第四步:检查驱动型号

如果以上都没问题还是白屏,试试换驱动:

  • ILI9341 → ST7789 → GC9A01 逐个试
  • 注意分辨率是否匹配(240×320 还是 240×240)

十、最终 GPIO 规划表

在这里插入图片描述


十一、调试经验总结

1. 不要只看"烧录成功"

烧录成功 ≠ 硬件正确。
需要分别验证每个模块:
模块验证方式WiFi看日志是否连上路由器MQTT看日志是否 Connected麦克风说唤醒词,看是否触发 Wake word detected播放AI 是否有语音输出屏幕是否正常显示,不是白屏按键GPIO 输入是否响应

2. ESP-IDF 和 Arduino 的区别

ArduinoESP-IDF定位快速验证原型正式产品开发适合场景点灯、传感器、简单项目AI、音频、多任务、DMA、FreeRTOS、硬件驱动学习曲线简单较陡性能一般高
后续如果要做:

  • 实时对讲
  • 实时音频流
  • 本地音频处理
    更适合用 ESP-IDF。

十二、下一步开发计划

基于当前环境继续扩展:

  • TFT UI 显示自定义界面
  • 自定义唤醒词
  • ESP32 实时对讲功能
  • 音频流传输
  • Electron 桌面端控制
  • Rust 音频处理模块

ESP32-S3 只是开始,后续将逐步构建完整 AI 硬件系统。


写在最后:

从最开始跟着教程用浏览器烧录,到后来因为屏幕不匹配被迫跳进 ESP-IDF 的坑,再到一步步解决 GPIO 冲突、屏幕白屏、音频无声的问题——
这整个过程,比单纯"学会烧录小智"有价值得多。
我积累的不是"小智烧录笔记",而是在形成一个完整 AI 硬件平台做开发的基础。
为今后对自己扩展知识范围,学习对讲设备、Electron 控制端、Rust 音频服务做基础。
与各位正在折腾 ESP32 的开发者共勉

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐