ESP32-S31-Touch-LCD-4.3C 使用教程

产品特性​

  • 搭载 ESP32-S31 双核 32 位 RISC-V 处理器,最高主频为 320 MHz。
  • 支持 128 位 SIMD(Single Instruction, Multiple Data,单指令多数据)指令,仅其中一个处理器核心支持该指令。
  • 芯片集成 JPEG 编解码器、PPA(Pixel-Processing Accelerator,像素处理加速器)和 2D-DMA(2D Direct Memory Access,二维直接存储器访问)控制器。
  • 支持 2.4 GHz Wi-Fi 6、Bluetooth 5.4(LE)、经典蓝牙(BR/EDR)和 IEEE 802.15.4,配备板载天线。
  • 芯片支持 Thread、Zigbee 和 Bluetooth Mesh 1.1,具体协议功能需配合相应 SDK 和固件使用。
  • 内置 512 KB 高性能 SRAM 和 320 KB ROM;采用 N16R16 模组,配备 16 MB Flash 和 16 MB PSRAM。
  • 板载 4.3 英寸 IPS 电容触摸 LCD,800 × 480 分辨率,65K 彩色,采用 16 位 RGB565 接口;标称可视角度为 160°。
  • 配备 GT911 电容触摸控制器,通过 I2C 通信,支持触摸中断;配套示例最多读取 5 个触点。
  • 提供 LVGL 图形界面开发示例,通过 PWM 调节背光亮度。
  • 板载 ES8389 音频编解码器、双麦克风和扬声器功放电路,用于音频采集、录音与语音播放应用开发。
  • 支持 Type-C 5 V 供电和 DC 7~36 V 输入,板载稳压电路。
  • 提供 3.7 V 单节锂电池接口、充电电路和 BQ27220 电量计,用于电池充电与电量监测。
  • 板载 RTC(Real-Time Clock,实时时钟)芯片和 CR927 备用电池座,安装备用电池后可在主电源断开时保持计时。
  • 支持半双工 RS485 和 CAN-FD 通信,引出 I2C 和 6 路原生 GPIO。
  • 板载 TF 卡座和六轴 IMU(Inertial Measurement Unit,惯性测量单元),便于资源存储、数据记录和运动感知。
  • 通过独立的 MX1.25 4PIN 接口引出原生 USB,提供 USB Host 枚举和外接 USB 摄像头显示示例。
  • 板载 PWR 电源指示灯、CHG 充电指示灯和 USER 可编程指示灯。
  • 芯片支持安全启动、Flash / PSRAM 加密,以及 TEE(Trusted Execution Environment,可信执行环境)和 APM(Access Permission Management,访问权限管理)。
  • 提供 16 个示例,覆盖显示、触摸、音频和主要板载外设。

板载资源​


与 ESP32-S3-Touch-LCD-4.3C 的主要差异​

项目ESP32-S3-Touch-LCD-4.3CESP32-S31-Touch-LCD-4.3C
主控ESP32-S3,Xtensa LX7 双核,最高 240 MHzESP32-S31,RISC-V 双核,最高 320 MHz
存储16 MB Flash、8 MB PSRAMN16R16:16 MB Flash、16 MB PSRAM
音频ES8311 与 ES7210ES8389
外部 IO隔离数字输入、输出GPIO48~53 原生 GPIO,无隔离
USB Host 座子未配置该座子新增 MX1.25 4PIN 座子 J3
下载通道原生 USBType-C → CH343P → UART0
配套开发示例Arduino、ESP-IDF当前资料仅提供 ESP-IDF

两款产品的 GPIO 分配和驱动配置不同。移植时需使用本产品的板级定义,不能只修改目标芯片名称或沿用 S3 固件。

原生 GPIO 电平

H4 的 GPIO48~53 没有 S3 版隔离 IO 的隔离与电平转换电路。使用 3.3 V 逻辑连接,并与外设共地;不得接入原隔离 IO 使用的高电压信号或将其作为功率输出。

接口与引脚​

LCD 与触摸​

LCD 与触摸引脚对照表
信号ESP32-S31 GPIO说明
LCD B3~B7GPIO8、9、10、11、12RGB565 蓝色数据,对应软件 D0~D4
LCD G2~G7GPIO13、14、15、16、17、18RGB565 绿色数据,对应软件 D5~D10
LCD R3~R7GPIO19、33、34、35、36RGB565 红色数据,对应软件 D11~D15
LCD PCLKGPIO40像素时钟
LCD DEGPIO43数据使能
LCD HSYNCGPIO44行同步
LCD VSYNCGPIO45场同步
LCD BL_PWMGPIO47背光调节
触摸 SDA、SCLGPIO0、GPIO1共用 I2C 总线
触摸 INTGPIO2触摸中断
触摸 RESETGPIO46触摸复位

I2C 总线与板载器件​

I2C 设备地址与控制引脚
器件7 位 I2C 地址中断或控制信号
GT911 触摸0x5D 或 0x14,取决于复位选址INT:GPIO2;RESET:GPIO46
ES8389 音频编解码器当前配置为 0x10I2S 音频数据及 GPIO57 功放控制
PCF85063ATL RTC0x51INT:GPIO3
QMI8658 IMU原理图及默认配置为 0x6B,软件另探测 0x6AINT1:GPIO54;INT2 至 GPIO60 的 R94 标注 NC
BQ27220 电量计0x55由电池侧供电

音频与 TF 卡​

音频与 TF 卡引脚对照表
功能信号ESP32-S31 GPIO
ES8389I2S BCLKGPIO37
ES8389I2S LRCK / WSGPIO38
ES8389主控 DOUT → 编解码器 DSDINGPIO39
ES8389主控 DIN ← 编解码器 ASDOUTGPIO42
扬声器功放PA_CTRL,高有效GPIO57
TF 卡CLK、CMDGPIO24、GPIO25
TF 卡D0、D1、D2、D3GPIO20、GPIO21、GPIO22、GPIO23
TF 卡供电SD_CTRL,低有效GPIO56

USB、RS485、CAN-FD 与按键​

通信接口与按键引脚对照表
功能信号或器件连接
Type-C 下载与日志CH343P 接 UART0TXD0:GPIO58;RXD0:GPIO59
USB HostJ3 的 D+、D−模组专用 USB_DP、USB_DM,非 GPIO40/41
USB Host 电源J3 VBUS板载 5 V 电源,无 GPIO 使能
RS485UART1 TX、RXGPIO6、GPIO7
RS485RTS / DEGPIO61
CAN-FDTX、RXGPIO4、GPIO5,经 MCP2562FD 收发器
BOOT 按键低有效GPIO61
RESET 按键低有效ESP_EN
状态 LEDGPIO 控制GPIO55;不是 Zero 的 WS2812 RGB LED

原理图中 RS485 方向控制与 BOOT 共用 GPIO61,运行 RS485 时不要按 BOOT。

扩展连接器​

以下针序以原理图的针脚编号为准,不代表从线缆某一面观察的左右顺序。接线前核对 PCB 丝印和连接器方向。

J3 USB Host 与 H4 扩展接口针序
连接器针脚信号
J3,MX1.25 4PIN1GND
J32USB D+
J33USB D-
J345 V
H41、2DC+、DC−
H43、4I2C_VCC、GND
H45、6SDA、SCL,经 I2C 电平转换电路
H47、8CANL、CANH
H49、10RS485 TX−、TX+
H411~16GPIO48、49、50、51、52、53

H4 的 SDA、SCL 具有 I2C 电平转换电路,扩展侧电压 I2C_VCC 通过硬件选择 3.3 V 或 5 V,原理图的 H3 注明默认连接 3.3 V。GPIO48~53 则为 3.3 V 原生 GPIO,不随 I2C_VCC 切换。电平选择与接线步骤见 I2C 扩展接口。

电池接口 J1 为 MX1.25 2PIN,用于连接 3.7 V 单节锂电池,连接前核对电池插头极性。

产品尺寸​

不带外壳​


带外壳​


使用说明

首次连接​

准备开发板、支持数据传输的 USB Type-C 线缆和电脑。首次连接时,断开电池、外部 DC 电源、USB Host 设备及其他扩展设备。

  1. 用 Type-C 线缆连接开发板与电脑,将电源开关置于开启位置。
  2. 在 Windows 设备管理器中查看新增串口。本板使用 CH343P USB 转串口芯片;若未出现串口,安装 CH343 Windows 串口驱动,并检查线缆是否支持数据传输。
  3. 按 ESP-IDF 开发 编译并下载 01_i2c_scan,确认板载总线应答,再选择显示或其他示例。

Type-C 下载串口与 J3 USB Host 是不同接口。下载程序时使用 Type-C,不将 J3 当作电脑下载接口。

供电与电池​

开发板支持 Type-C 5 V 供电、DC 7~36 V 输入和 3.7 V 单节锂电池供电,首次连接建议使用 Type-C。接入电池或外部 DC 电源前断开供电,按原理图与 PCB 丝印核对接口和极性。DC 输入连接 H4 的 1 脚 DC+、2 脚 DC−,不将 DC 输入电压接到 5 V、I2C 或 GPIO 引脚。

接口或器件说明
J1 电池接口MX1.25 2PIN,连接 3.7 V 单节锂电池;不得仅凭线色判断极性
ETA6098电池充电电路
MP28164GD-Z电池升压电路
BQ27220电量计,直接由电池侧供电;未连接电池时无法应答
CR927 电池座RTC 备用电源,安装后用于主电源断开时保持计时;不代替 J1 的系统供电电池

04_bat_bq27220 中的 650 mAh 是软件设计容量参数,不表示板载电池容量或固定适配容量。容量、电流方向及荷电状态需结合实际电池和电量计配置判断,不能将显示值当作已校准的测量结果。

带壳版本的电池仓可容纳尺寸为 60 × 30 × 6 mm(长 × 宽 × 厚)的电池。选配时同时核对电池尺寸、电气规格和插头极性;是否随附电池以所选产品配置为准。

PWR 用于指示电源状态,CHG 用于指示充电状态,USER 为 GPIO55 控制的可编程指示灯;CHG 不作为电池剩余电量的百分比指示。


I2C 扩展接口​

H4 的 3 脚为 I2C_VCC、4 脚为 GND、5 脚为 SDA、6 脚为 SCL。扩展侧 SDA、SCL 经过电平转换电路,I2C_VCC 可通过板上硬件连接选择 3.3 V 或 5 V;原理图的 H3 注明默认连接 3.3 V。

  1. 断电后,确认外部 I2C 设备的供电和逻辑电平要求。
  2. 核对板上的电压选择连接;需要切换时按原理图的 H3 配置操作,3.3 V 与 5 V 二选一,不同时连通。
  3. 将外设连接至 I2C_VCC、GND、SDA 和 SCL,确认极性及电平后再上电。

I2C_VCC 由硬件选择,不能通过软件切换。H4 的 GPIO48~53 始终按 3.3 V 原生 GPIO 使用,不随 I2C 扩展侧电压改变。

连接 USB Host 设备​

J3 是 MX1.25 4PIN USB Host 接口。使用针序匹配的转接线,将外部 USB 设备接入开发板。

J3 针脚信号
1GND
2USB D+
3USB D−
45 V
  1. 断电后核对转接线针序与连接器方向。
  2. 接入设备,确认设备供电需求与板卡供电条件匹配,再给开发板上电。
  3. 运行 10_usb_host,查看连接、断开及 VID、PID 等枚举信息。

J3 的 VBUS 接板载 5 V,没有软件控制使能;不要向该引脚反向供电。枚举成功只说明 USB 设备已识别,使用键盘、存储设备或其他设备还需要对应的 USB 类驱动。

运行 16_usb_camera 时,需通过 J3 外接支持匹配 MJPEG 模式的 UVC 摄像头。

使用 TF 卡与音频​

  1. 备份 TF 卡数据,使用示例支持的 FAT 文件系统。测试会写入文件,不使用含唯一副本数据的卡。
  2. 断电后插入 TF 卡。
  3. 将源码包内 examples/esp-idf/07_codec_sd_wav_player/test.wav 复制到 TF 卡根目录。
  4. 上电后运行 07_codec_sd_wav_player,检查测试音与扫频声音。

当前 TF 卡配置为 4 位 SDMMC,GPIO56 低电平使能卡电源;GPIO57 高电平使能扬声器功放。原理图中的扬声器功放只连接 ES8389 左声道差分输出,不能仅凭测试文件中的纯右声道片段无声判断扬声器故障。

连接 GPIO、RS485 与 CAN-FD​

  • H4 的 GPIO48~53 为 3.3 V 原生 GPIO,连接外设时共地。
  • RS485 使用 H4 的 9 脚 TX−、10 脚 TX+;通信对端配置为 115200、8 位数据、无校验、1 位停止位。运行时不要按下与方向控制共用 GPIO61 的 BOOT 按键。
  • CAN-FD 使用 H4 的 7 脚 CANL、8 脚 CANH。配套示例使用 500 kbit/s 仲裁速率和 2 Mbit/s 数据速率,对端需匹配 CAN-FD 与位速率切换配置。
  • CAN 总线应按拓扑配置两端终端电阻。原理图提供 SW2 控制的 120 Ω 终端电阻,按板卡在总线中的实际位置设置。

具体针脚见 扩展连接器。连接外部设备前断电,确认信号类型、极性、电平和共地条件。


ESP-IDF

本章节包含以下部分,请按需阅读:

ESP-IDF 入门教程​

初次接触 ESP32 ESP-IDF 开发,想要快速上手?我们为您准备了一套通用的 入门教程。

请注意:该教程使用 ESP32-S3-Zero 作为教学示例,所有硬件代码均基于其引脚布局。在动手实践前,建议您对照手中的开发板引脚图,确认引脚配置无误。

配置 ESP-IDF 开发环境​

ESP-IDF 版本​

配套示例使用 ESP-IDF v6.1,目标芯片为 esp32s31。下方通用安装图示中的版本号仅作演示。

备注

以下内容以 Windows 系统为例,使用 VS Code + ESP-IDF 扩展 的方式进行开发。Mac/Linux 用户请参考 官方说明。

版本选择

此部分图示以安装 ESP-IDF V5.5.2 为例示范,安装时请选用与您开发板示例匹配的 ESP-IDF 版本。

安装 ESP-IDF 开发环境​

  1. 前往 ESP-IDF Installation Manager 下载 ESP-IDF 安装管理器。这是乐鑫最新推出的跨平台安装工具,下文将演示如何使用其离线安装功能。

    在页面中点击 Offline Installer 标签,然后在筛选栏中选择 Windows 操作系统和你需要的 ESP-IDF 版本(图示仅为参考,请以实际为准)。


    确认选择无误后,点击下载按钮。浏览器将自动同时下载两个文件:一个是 ESP-IDF 离线整合包(.zst),另一个是 ESP-IDF 安装器(.exe)。


    请耐心等待两个文件下载完成。

  2. 下载完成后,双击运行 ESP-IDF 安装器(eim-gui-windows-x64.exe)。

    启动后,可在右上角将界面语言切换为中文。


    安装工具会自动检测同一目录下是否存在离线整合包。点击 从存档安装。


    接下来,选择安装路径。建议使用默认路径;若需自定义,请确保路径中不包含中文或空格。确认无误后,点击 开始安装。


  3. 当看到如下界面时,表示 ESP-IDF 已安装成功。


  4. 建议同时安装驱动程序。点击 完成安装,然后点击 安装驱动程序。


安装 Visual Studio Code 与 ESP-IDF 扩展​

  1. 下载并安装 Visual Studio Code。

  2. 安装时建议勾选 通过 Code 打开操作添加到 Windows 资源管理器文件上下文菜单,以便快速打开项目文件夹。

  3. 在 VS Code 中,点击侧边活动栏中的 扩展图标 扩展图标(或使用快捷键 Ctrl + Shift + X)打开 扩展 视图。

  4. 在搜索框中输入 ESP-IDF,找到 ESP-IDF 扩展并点击安装。


  5. 当 ESP-IDF 扩展版本 ≥ 2.0 时,扩展会自动检测并识别上述步骤中安装的 ESP-IDF 环境,无需手动配置。

准备工程与板级定义​

以下以 01_i2c_scan 为例,使用 ESP-IDF v6.1 终端执行命令。

  1. 下载 ESP32-S31-Touch-LCD-4.3C 示例程序,解压到较短且不含中文或空格的路径。

  2. 在 VS Code 中打开其中一个示例的工程目录,例如 examples/esp-idf/01_i2c_scan。按 Ctrl + Shift + P 打开命令面板,运行 "ESP-IDF: Open ESP-IDF Terminal"。

  3. 在终端中安装板级代码生成工具,同一个 ESP-IDF 环境只需安装一次:

    python -m pip install esp-bmgr-assist
  4. 设置当前终端的目标芯片。每次新建 ESP-IDF 终端后都需重新设置:

    $env:IDF_TARGET = "esp32s31"
  5. 生成当前示例的板级代码并编译,首次执行需联网下载所需组件:

    idf.py bmgr -b esp32_s31_touch_lcd_4_3c
    idf.py build
  6. 用 Type-C 数据线连接开发板,开启电源开关。在设备管理器中确认 CH343P 串口号,将下列 COMx 替换为实际串口号,下载程序并打开串口监视器:

    idf.py -p COMx flash monitor

    串口应周期输出 I2C 应答地址与扫描统计,结果判断见 I2C 扫描。

按 Ctrl + ] 退出串口监视器。运行其他示例时,打开对应工程目录和 ESP-IDF 终端,重复目标芯片设置、板级代码生成、编译和下载步骤。

使用 VS CODE 扩展工具

使用 VS Code 的 ESP-IDF 扩展按钮编译前,先打开当前示例的工程目录,运行 "ESP-IDF: Open ESP-IDF Terminal",或点击 VS Code 打开 ESP-IDF 终端按钮 打开 ESP-IDF 终端,再按顺序完成以下准备:

  1. 安装板级代码生成工具。同一个 ESP-IDF 环境只需安装一次,已安装可跳过:

    python -m pip install esp-bmgr-assist
  2. 设置当前终端的目标芯片。每次新建 ESP-IDF 终端后都需重新设置:

    $env:IDF_TARGET = "esp32s31"
  3. 生成当前示例的板级代码:

    idf.py bmgr -b esp32_s31_touch_lcd_4_3c
  4. 配置当前工程:

    idf.py reconfigure

以上命令执行成功后,可使用扩展按钮编译、烧录和监视。切换到其他示例工程时,需在对应工程的 ESP-IDF 终端中重新设置目标芯片、生成板级代码并配置工程。

示例程序​

所有工程位于 examples/esp-idf/,分别打开对应文件夹,按 板级配置与编译下载步骤 操作。

折叠代码用于讲解关键流程,省略了头文件、部分初始化或错误处理。编译时使用完整工程,完整源码见 ESP32-S31-Touch-LCD-4.3C 示例源码包。

示例目录功能外接条件或结果判断
01_i2c_scan扫描共用 I2C 总线无电池时电量计可能不应答
02_rtc_pcf85063atl读写 RTC、1 Hz 定时中断初始时间是示例值,不自动校时
03_imu_qmi8658读取温度、加速度和角速度改变姿态观察数据
04_bat_bq27220读取电量计需连接适配电池
05_tf_cardTF 卡文件读写与目录列表FAT 格式 TF 卡,先备份数据
06_codec_mic_raw采集麦克风原始数据检查双声道采样及峰值变化
07_codec_sd_wav_player播放 TF 卡 WAV 文件TF 卡、匹配扬声器和 WAV 文件
08_rs485半双工 RS485 收发RS485 对端与匹配接线
09_canfdCAN-FD 收发CAN-FD 对端与正确终端电阻
10_usb_host外部 USB 设备枚举J3 转接线和 USB 设备
11_rgb_lcdRGB LCD 测试图案板载显示屏
12_touch触摸轨迹和清屏板载触摸屏
13_comprehensive_test综合测试仪表界面各项目分别需要电池、TF 卡、通信对端等
14_lvgl_portingLVGL 图形与触摸交互使用工程指定的 LVGL 依赖
15_bluetooth_speaker经典蓝牙 A2DP 音箱音频发送设备与匹配扬声器
16_usb_camera外接 USB 摄像头预览匹配 MJPEG 模式的 UVC 摄像头

01_i2c_scan:I2C 扫描​

本示例演示扫描板载 I2C 总线,输出应答设备的 7 位地址、总线空闲电平和超时信息。

硬件连接​

  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。
  • 使用板载 SDA GPIO0、SCL GPIO1,无需外接 I2C 模块。

代码​

main/main.c 关键代码
esp_err_t touch_ret = esp_board_manager_init_device_by_name("lcd_touch");
if (touch_ret == ESP_OK) {
touch_ret = esp_board_manager_deinit_device_by_name("lcd_touch");
if (touch_ret != ESP_OK) {
ESP_LOGE(TAG, "touch release failed: %s", esp_err_to_name(touch_ret));
ret = touch_ret;
goto cleanup;
}
} else {
ESP_LOGW(TAG, "touch wake-up failed: %s", esp_err_to_name(touch_ret));
}
vTaskDelay(pdMS_TO_TICKS(10));

// ...

for (uint8_t address = 0x03; address <= 0x77; address++) {
esp_err_t probe_ret = i2c_master_probe(bus, address, SCAN_TIMEOUT_MS);
if (probe_ret == ESP_OK) {
ESP_LOGI(TAG, "found 0x%02x %s",
(unsigned)address, known_device_name(address));
found++;
} else if (probe_ret == ESP_ERR_TIMEOUT) {
timeout++;
} else if (probe_ret != ESP_ERR_NOT_FOUND) {
other_error++;
ESP_LOGW(TAG, "probe 0x%02x failed: %s",
(unsigned)address, esp_err_to_name(probe_ret));
}
}

代码解释​

  • esp_board_periph_ref_handle():获取 Board Manager 创建的 I2C0 总线句柄。
  • esp_board_manager_init_device_by_name("lcd_touch"):初始化触摸设备,完成 GT911 的复位、唤醒和选址,再释放设备以进行扫描。
  • i2c_master_probe():探测 0x03~0x77,分别统计应答、超时及其他错误;扫描前由 i2c_bus_is_idle() 检查总线电平。

运行效果​

  • 串口周期输出应答地址和扫描统计,地址含义见 I2C 设备表。
  • GT911 可应答 0x5D 或 0x14;BQ27220 未连接电池时可能不应答。不要将所有配置地址都作为必须出现的扫描结果。


02_rtc_pcf85063atl:实时时钟​

本示例演示 PCF85063ATL 的时间读写、1 Hz 定时中断及中断状态读取。

硬件连接​

  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。
  • 使用板载 RTC 和 GPIO3 中断信号,无需外接模块。
  • 如需检查主电源断开后的计时保持,先安装 CR927 备用电池;RTC 备用电池与 J1 的系统供电锂电池是不同接口。

代码​

main/main.c 关键代码
void app_main(void)
{
s31_rtc_handle_t *rtc = NULL;
ESP_ERROR_CHECK(s31_rtc_acquire(&rtc));
ESP_ERROR_CHECK(s31_rtc_start_1hz_interrupt(rtc));

s31_rtc_time_t now = {0};
ESP_ERROR_CHECK(s31_rtc_get_time(rtc, &now));
if (now.voltage_low || now.year < 2024 || now.month == 0 || now.day == 0) {
const s31_rtc_time_t initial = {
.year = 2026, .month = 1, .day = 1, .weekday = 4,
.hour = 12, .minute = 0, .second = 0,
};
ESP_LOGW(TAG, "invalid RTC time; setting 2026-01-01 12:00:00");
ESP_ERROR_CHECK(s31_rtc_set_time(rtc, &initial));
}

uint32_t last_interrupt = 0;
while (true) {
ESP_ERROR_CHECK(s31_rtc_get_time(rtc, &now));
ESP_LOGI(TAG, "%04u-%02u-%02u %02u:%02u:%02u weekday=%u VL=%d",
now.year, now.month, now.day, now.hour, now.minute, now.second,
now.weekday, now.voltage_low);
s31_rtc_interrupt_status_t status = {0};
ESP_ERROR_CHECK(s31_rtc_get_interrupt_status(rtc, &status));
if (status.count != last_interrupt) {
ESP_LOGI(TAG, "INT count=%lu level=%d control2=0x%02x",
(unsigned long)status.count, status.gpio_level, status.control2);
ESP_ERROR_CHECK(s31_rtc_clear_interrupt(rtc));
last_interrupt = status.count;
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}

代码解释​

  • s31_rtc_acquire():获取 RTC 设备;s31_rtc_start_1hz_interrupt() 启用 1 Hz 定时中断。
  • s31_rtc_get_time() / s31_rtc_set_time():读取和设置时间;检测到时间无效时,设为 2026-01-01 12:00:00。
  • s31_rtc_get_interrupt_status() / s31_rtc_clear_interrupt():读取中断计数和 GPIO3 状态,并清除中断标志。

运行效果​

  • 串口输出日期、时间及中断状态,观察秒数递增和中断计数变化。
  • 默认时间是示例值,不代表当前时间,也不会自动校时。需要准确时间时,修改初始化值或实现校时;掉电保持需具备实际的 RTC 备用电源条件。


03_imu_qmi8658:六轴传感器​

本示例演示读取 QMI8658 的器件标识、数据就绪状态、温度、加速度、角速度及 GPIO54 中断状态。

硬件连接​

  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。
  • 使用板载 QMI8658,测试时缓慢改变开发板姿态。

代码​

main/main.c 关键代码
void app_main(void)
{
s31_imu_handle_t *imu = NULL;
ESP_ERROR_CHECK(s31_imu_acquire(&imu));
uint8_t who = 0;
uint8_t revision = 0;
ESP_ERROR_CHECK(s31_imu_get_identity(imu, &who, &revision));
ESP_LOGI(TAG, "WHO_AM_I=0x%02x revision=0x%02x", who, revision);

uint32_t sample = 0;
while (true) {
bool ready = false;
uint8_t status_int = 0;
uint8_t status0 = 0;
esp_err_t ret = s31_imu_is_data_ready(imu, &ready, &status_int, &status0);
if (ret == ESP_OK && ready) {
s31_imu_data_t data = {0};
ESP_ERROR_CHECK(s31_imu_read(imu, &data));
ESP_LOGI(TAG,
"sample=%lu acc[g]=%+.3f,%+.3f,%+.3f gyro[dps]=%+.2f,%+.2f,%+.2f temp=%.2fC int=0x%02x status0=0x%02x gpio=%d",
(unsigned long)++sample, data.accel_x_g, data.accel_y_g,
data.accel_z_g, data.gyro_x_dps, data.gyro_y_dps,
data.gyro_z_dps, data.temperature_c, data.status_int,
data.status0, data.int_gpio_level);
} else if (ret != ESP_OK) {
ESP_LOGW(TAG, "status read failed: %s", esp_err_to_name(ret));
} else {
ESP_LOGD(TAG, "waiting: INT=0x%02x STATUS0=0x%02x", status_int, status0);
}
vTaskDelay(pdMS_TO_TICKS(100));
}
}

代码解释​

  • s31_imu_acquire() / s31_imu_get_identity():初始化传感器并读取器件标识与修订号。
  • s31_imu_is_data_ready():检查是否有可读取的数据。
  • s31_imu_read():读取各轴加速度、角速度、温度及中断状态,并通过日志输出。

运行效果​

  • 串口持续输出采样数据,改变姿态时观察各轴读数变化。
  • 该示例不包含成品姿态融合或运动精度校准。


04_bat_bq27220:电量计​

本示例演示通过 BQ27220 读取电池电压、电流、温度、容量、荷电状态和状态标志。

硬件连接​

  • 断电后按 J1 极性连接适配电池,核对插头正负极。
  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。

代码​

main/main.c 关键代码
void app_main(void)
{
while (true) {
s31_battery_handle_t *battery = NULL;
esp_err_t ret = s31_battery_acquire(&battery);
if (ret != ESP_OK) {
ESP_LOGE(TAG,
"BQ27220 is not responding: %s. The gauge is powered from "
"the battery; connect a battery and verify the I2C bus with "
"01_i2c_scan. Retrying...",
esp_err_to_name(ret));
vTaskDelay(pdMS_TO_TICKS(BATTERY_RETRY_DELAY_MS));
continue;
}

ESP_LOGI(TAG, "BQ27220 detected");
while (true) {
s31_battery_info_t info = {0};
ret = s31_battery_get_info(battery, &info);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "BQ27220 read failed: %s", esp_err_to_name(ret));
break;
}
ESP_LOGI(TAG,
"voltage=%umV current=%dmA avg=%dmA power=%dmW cap=%u/%umAh soc=%u%% soh=%u%% temp=%.1fC cycles=%u max_load=%dmA tte=%umin ttf=%umin status=0x%04x",
info.voltage_mv, info.current_ma, info.average_current_ma,
info.average_power_mw, info.remaining_capacity_mah,
info.full_charge_capacity_mah, info.state_of_charge_percent,
info.state_of_health_percent, info.temperature_c,
info.cycle_count, info.max_load_ma, info.time_to_empty_min,
info.time_to_full_min, info.status);
vTaskDelay(pdMS_TO_TICKS(BATTERY_RETRY_DELAY_MS));
}

ret = s31_battery_release();
if (ret != ESP_OK) {
ESP_LOGW(TAG, "BQ27220 release failed: %s", esp_err_to_name(ret));
}
vTaskDelay(pdMS_TO_TICKS(BATTERY_RETRY_DELAY_MS));
}
}

代码解释​

  • s31_battery_acquire():获取电量计;未供电或初始化失败时,每 2 秒重试。
  • s31_battery_get_info():周期读取电池信息;读取失败后释放设备并重试。
  • 设计容量 650 mAh 是软件参数,需根据实际电池配置。

运行效果​

  • 串口输出电池电压、电流、容量和状态等信息。
  • 若提示电量计不应答,先确认电池供电,再用 01_i2c_scan 检查 0x55;不要仅凭初始化失败判定开发板损坏。


05_tf_card:TF 卡读写​

本示例演示 TF 卡供电控制、文件系统挂载、测试文件写入与读回,以及根目录列表。

测试文件覆盖

示例以写入模式打开 /sdcard/s31_tf_card_demo.txt,同名文件会被覆盖。备份数据后再运行。

硬件连接​

  • 备份 TF 卡数据,断电后插入 FAT 格式 TF 卡。
  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。

代码​

main/main.c 关键代码
char path[512];
int len = snprintf(path, sizeof(path), "%s/s31_tf_card_demo.txt", sd->mount_point);
if (len <= 0 || (size_t)len >= sizeof(path)) {
ESP_LOGE(TAG, "Test file path is too long");
goto cleanup;
}

FILE *file = fopen(path, "w");
if (!file) {
ESP_LOGE(TAG, "Failed to open %s for writing", path);
goto cleanup;
}
int write_ret = fputs("ESP32-S31 TF card demo OK\n", file);
int close_ret = fclose(file);
if (write_ret == EOF || close_ret != 0) {
ESP_LOGE(TAG, "Failed to write %s", path);
goto cleanup;
}
ESP_LOGI(TAG, "wrote %s", path);

char line[64] = {0};
file = fopen(path, "r");
if (!file) {
ESP_LOGE(TAG, "Failed to open %s for reading", path);
goto cleanup;
}
if (!fgets(line, sizeof(line), file)) {
ESP_LOGE(TAG, "Failed to read %s", path);
fclose(file);
goto cleanup;
}
fclose(file);
ESP_LOGI(TAG, "read back: %s", line);

代码解释​

  • esp_board_manager_init_device_by_name("fs_sdcard"):使能 TF 卡电源并挂载文件系统;默认挂载失败不会自动格式化。
  • fopen() / fputs() / fgets():以写入模式创建测试文件,再打开文件读回内容。
  • list_root():每 5 秒列出根目录。当前使用 4 位 SDMMC,GPIO56 低有效;排查失败时先确认供电、文件系统和板级配置。

运行效果​

  • 串口输出测试文件路径和读回的 ESP32-S31 TF card demo OK,随后周期输出根目录内容。


06_codec_mic_raw:麦克风采样​

本示例演示通过 ES8389 以 48 kHz、16 位、双声道采集麦克风原始音频。

硬件连接​

  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。
  • 使用板载双麦克风,无需外接音源。

代码​

main/main.c 关键代码
ESP_ERROR_CHECK(esp_board_manager_init_device_by_name("audio_adc"));
dev_audio_codec_handles_t *adc = NULL;
ESP_ERROR_CHECK(esp_board_manager_get_device_handle("audio_adc", (void **)&adc));
ESP_ERROR_CHECK(adc && adc->codec_dev ? ESP_OK : ESP_ERR_INVALID_STATE);

esp_codec_dev_sample_info_t format = {
.sample_rate = SAMPLE_RATE,
.channel = CHANNELS,
.bits_per_sample = 16,
.mclk_multiple = 256,
};
ESP_ERROR_CHECK(esp_codec_dev_open(adc->codec_dev, &format) == ESP_CODEC_DEV_OK ? ESP_OK : ESP_FAIL);
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(adc->codec_dev, 30.0f) == ESP_CODEC_DEV_OK ? ESP_OK : ESP_FAIL);

// ...

while (true) {
ESP_ERROR_CHECK(esp_codec_dev_read(adc->codec_dev, samples, BUFFER_BYTES) == ESP_CODEC_DEV_OK
? ESP_OK : ESP_FAIL);
int32_t left_peak = 0;
int32_t right_peak = 0;
for (int i = 0; i < FRAME_SAMPLES; i++) {
int32_t left = abs(samples[i * 2]);
int32_t right = abs(samples[i * 2 + 1]);
left_peak = left > left_peak ? left : left_peak;
right_peak = right > right_peak ? right : right_peak;
}
ESP_LOGI(TAG,
"frame=%" PRIu32 " peak L=%ld R=%ld first samples: [%d,%d] [%d,%d] [%d,%d] [%d,%d]",
frame++, (long)left_peak, (long)right_peak,
samples[0], samples[1], samples[2], samples[3],
samples[4], samples[5], samples[6], samples[7]);

代码解释​

  • esp_board_manager_init_device_by_name("audio_adc"):初始化 ES8389 音频输入设备。
  • esp_codec_dev_open() / esp_codec_dev_set_in_gain():设置采样格式和输入增益。
  • esp_codec_dev_read():读取双声道采样数据;循环分别计算左右声道峰值并输出部分采样值。

运行效果​

  • 对麦克风说话,观察串口中左右声道的峰值及采样值随声音变化。
  • 该示例仅采集原始音频,不包含语音识别或回声消除。


07_codec_sd_wav_player:WAV 播放​

本示例演示从 TF 卡读取 16 位 PCM(Pulse Code Modulation,脉冲编码调制)WAV 文件,经 ES8389 和板载功放播放。

硬件连接​

  • 按 TF 卡与音频准备 复制 test.wav 并连接匹配的扬声器。
  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。

代码​

main/main.c 关键代码

代码解释​

  • esp_board_manager_init_device_by_name():分别初始化 fs_sdcard 和 audio_dac;ES8389 配置启用 DAC 参考,功放由 GPIO57 控制。
  • find_wav():优先查找 /sdcard/test.wav,否则选择根目录中的首个 WAV 文件。
  • play_wav():解析并播放 16 位 PCM 单声道或双声道 WAV,单声道转换为双声道播放;播放完成后等待 1 秒再循环。该工程不是通用 MP3 播放器。

运行效果​

  • 串口输出选中的文件、播放状态和循环提示,结合扬声器声音检查播放情况。
  • 包内 test.wav 为 6 秒诊断信号,包含左声道音、右声道音和双声道扫频。功放只接 ES8389 左声道差分输出,不能仅凭纯右声道片段无声判断扬声器故障。
  • 日志中的写入成功仅表示音频数据已写入,播放是否正常需结合实际声音判断。有噪声或无声时,按 音频排查 检查。


08_rs485:RS485 收发​

本示例演示半双工 RS485 的周期发送和接收,不包含 Modbus 协议栈。

硬件连接​

  • 断电后将 H4 的 TX−、TX+ 接至极性匹配的 RS485 对端,并确认参考地。
  • 对端设置为 115200、8N1、无硬件流控。
  • 使用 USB 数据线将开发板 Type-C 接口连接电脑;运行时不要按下与方向控制共用 GPIO61 的 BOOT。

代码​

main/main.c 关键代码
periph_uart_handle_t *uart = NULL;
periph_uart_config_t *config = NULL;
ESP_ERROR_CHECK(esp_board_periph_ref_handle("uart_rs485", (void **)&uart));
ESP_ERROR_CHECK(esp_board_manager_get_periph_config("uart_rs485", (void **)&config));
ESP_ERROR_CHECK(uart ? ESP_OK : ESP_ERR_INVALID_STATE);
ESP_ERROR_CHECK(config ? ESP_OK : ESP_ERR_INVALID_STATE);
ESP_LOGI(TAG, "using uart_rs485: UART%d TX=GPIO%d RX=GPIO%d RTS/DE=GPIO%d baud=%d",
uart->uart_num, config->tx_io_num, config->rx_io_num,
config->rts_io_num, config->uart_config.baud_rate);

uint8_t rx[RX_BUFFER_SIZE];
uint32_t counter = 0;
while (true) {
char tx[96];
int length = snprintf(tx, sizeof(tx), "ESP32-S31 RS485 counter=%" PRIu32 "\r\n", counter++);
uart_write_bytes(uart->uart_num, tx, length);
uart_wait_tx_done(uart->uart_num, pdMS_TO_TICKS(100));
int rx_len = uart_read_bytes(uart->uart_num, rx, sizeof(rx) - 1, pdMS_TO_TICKS(500));
if (rx_len > 0) {
rx[rx_len] = 0;
ESP_LOGI(TAG, "RX %d byte(s): %s", rx_len, (char *)rx);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}

代码解释​

  • esp_board_periph_ref_handle("uart_rs485"):获取板级 UART 句柄,并读取 TX、RX、RTS / DE 和波特率配置。
  • uart_write_bytes() / uart_wait_tx_done():发送递增计数文本并等待发送完成。
  • uart_read_bytes():读取对端数据,接收成功时输出字节数和内容。

运行效果​

  • 对端周期收到 ESP32-S31 RS485 counter=...。
  • 从对端发送数据,检查开发板串口中的接收内容,确认双向通信。


09_canfd:CAN-FD 收发​

本示例演示 CAN-FD 帧发送与接收,发送 ID 为 0x123、数据长度为 16 字节。

硬件连接​

  • 断电后连接 CANH、CANL 和所需参考地,按总线拓扑配置终端电阻。
  • 对端设置仲裁速率 500 kbit/s、数据速率 2 Mbit/s,并支持 CAN-FD 位速率切换。
  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。

代码​

main/main.c 关键代码
uint8_t payload[16] = {0};
memcpy(payload, "S31 CAN FD", 10);
payload[12] = (uint8_t)(counter >> 24);
payload[13] = (uint8_t)(counter >> 16);
payload[14] = (uint8_t)(counter >> 8);
payload[15] = (uint8_t)counter;
twai_frame_t frame = {
.header.id = 0x123,
.header.dlc = twaifd_len2dlc(sizeof(payload)),
.header.fdf = true,
.header.brs = true,
.buffer = payload,
.buffer_len = sizeof(payload),
};
ret = twai_node_transmit(node, &frame, pdMS_TO_TICKS(100));

代码解释​

  • s31_canfd_acquire() / s31_canfd_enable():获取并使能板级 CAN-FD 设备,注册接收回调。
  • twai_frame_t:设置 ID、数据长度、FD 标志和 BRS 位速率切换标志,数据尾部包含计数值。
  • twai_node_transmit():提交发送;接收回调与任务负责记录对端帧的 ID、长度、FD 和 BRS 标志。

运行效果​

  • 在对端检查 ID 为 0x123 的 16 字节 CAN-FD 帧,并发送数据检查开发板接收日志。


10_usb_host:USB 枚举​

本示例演示 USB Host 设备枚举,输出连接、断开、速度、VID、PID 和设备类信息。

硬件连接​

  • 按 USB Host 接线 通过 MX1.25 4PIN 转接线将 USB 设备接入 J3。
  • VBUS 来自板载 5 V,无 GPIO 使能;接线前核对 J3 针序。
  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。

代码​

main/main.c 关键代码
static void client_event(const usb_host_client_event_msg_t *event, void *arg)
{
(void)arg;
if (event->event == USB_HOST_CLIENT_EVENT_NEW_DEV) {
usb_device_handle_t device = NULL;
if (usb_host_device_open(s_client, event->new_dev.address, &device) == ESP_OK) {
usb_device_info_t info = {0};
if (usb_host_device_info(device, &info) == ESP_OK) {
ESP_LOGI(TAG, "device %u speed=%s config=%u",
event->new_dev.address, usb_speed_text(info.speed),
info.bConfigurationValue);
}
const usb_device_desc_t *descriptor = NULL;
if (usb_host_get_device_descriptor(device, &descriptor) == ESP_OK) {
ESP_LOGI(TAG, "device %u VID=0x%04x PID=0x%04x class=0x%02x",
event->new_dev.address, descriptor->idVendor,
descriptor->idProduct, descriptor->bDeviceClass);
}
usb_host_device_close(s_client, device);
}
} else if (event->event == USB_HOST_CLIENT_EVENT_DEV_GONE) {
ESP_LOGI(TAG, "device disconnected");
}
}

代码解释​

  • usb_host_install() / usb_host_client_register():安装主机驱动并注册异步客户端。
  • usb_host_lib_handle_events() / usb_host_client_handle_events():分别处理主机库和客户端事件。
  • client_event():处理新设备与断开事件,读取设备信息和描述符后输出日志。

运行效果​

  • 连接设备后查看速度、VID、PID 和设备类;断开后查看断开事件日志。
  • 该示例只识别设备并报告连接、断开事件。使用设备的具体功能还需相应的 USB 类驱动。


11_rgb_lcd:显示测试​

本示例演示使用 PSRAM 双帧缓冲循环显示 LCD 测试图案。

硬件连接​

  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。
  • 使用板载 LCD,无需外接显示屏。

代码​

main/main.c 关键代码
while (true) {
uint16_t *frame = frames[frame_index];
draw_pattern(frame, config->lcd_width, config->lcd_height, pattern);
sync_frame(frame, config->lcd_width, config->lcd_height);
ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(lcd->panel_handle,
0, 0,
config->lcd_width,
config->lcd_height,
frame));

if (!backlight_enabled) {
vTaskDelay(pdMS_TO_TICKS(LCD_FIRST_FRAME_SETTLE_MS));
ESP_ERROR_CHECK(esp_board_manager_init_device_by_name("lcd_brightness"));
backlight_enabled = true;
}

pattern = (pattern + 1) % 8;
vTaskDelay(pdMS_TO_TICKS(1000));
frame_index ^= 1U;
}

代码解释​

  • esp_lcd_rgb_panel_get_frame_buffer():获取两个 RGB LCD 帧缓冲。
  • draw_pattern() / sync_frame():生成测试图案并同步缓冲数据;esp_lcd_panel_draw_bitmap() 提交画面。
  • 首帧完成后初始化 lcd_brightness 使能背光,每隔约 1 秒切换图案和帧缓冲。

运行效果​

  • 屏幕循环显示白、红、绿、蓝、八色条、棋盘、渐变和几何图案,检查颜色、边界和图案是否完整。
  • 显示配置为 800 × 480、RGB565,像素时钟为 26 MHz。


12_touch:触摸测试​

本示例演示读取最多 5 个触点,在屏幕绘制彩色标记,并通过右上角区域清屏。

硬件连接​

  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。
  • 使用板载 GT911 触摸屏,无需外接模块。

代码​

main/main.c 关键代码
ESP_ERROR_CHECK(esp_lcd_touch_read_data(touch->touch_handle));
uint16_t x[MAX_POINTS] = {0};
uint16_t y[MAX_POINTS] = {0};
uint16_t strength[MAX_POINTS] = {0};
uint8_t points = 0;
if (esp_lcd_touch_get_coordinates(touch->touch_handle, x, y, strength,
&points, MAX_POINTS)) {
bool clear_requested = false;
for (uint8_t i = 0; i < points; i++) {
if (touch_in_clear_block(x[i], y[i], lcd_config->lcd_width)) {
clear_requested = true;
break;
}
}
if (clear_requested) {
ESP_ERROR_CHECK(draw_page(lcd->panel_handle, lcd_config->lcd_width,
lcd_config->lcd_height, line));
ESP_LOGI(TAG, "clear screen");
} else {
for (uint8_t i = 0; i < points; i++) {
ESP_ERROR_CHECK(draw_mark(lcd->panel_handle, lcd_config->lcd_width,
lcd_config->lcd_height, x[i], y[i],
s_colors[i % MAX_POINTS], mark));
ESP_LOGI(TAG, "touch=%" PRIu32 " point=%u x=%u y=%u strength=%u",
count++, i, x[i], y[i], strength[i]);
}
}

代码解释​

  • esp_board_manager_init_device_by_name():初始化 LCD、触摸和背光,获取相应设备句柄。
  • esp_lcd_touch_read_data() / esp_lcd_touch_get_coordinates():读取触摸数据并获取坐标、强度和触点数。
  • touch_in_clear_block():判断是否触摸清屏区域;其他区域调用 draw_mark() 绘制标记并记录坐标。

运行效果​

  • 依次触摸屏幕四角、中间和右上角清屏区域,检查标记位置、坐标方向和清屏行为。
  • 初始化完成后,还需分别检查屏幕边缘、连续移动和多点输入,确认各区域的触摸响应。


13_comprehensive_test:综合测试​

本示例通过 LVGL 仪表界面组织显示、触摸、RTC、IMU、电量计、TF 卡、音频、RS485、CAN-FD、USB Host 和 Wi-Fi 扫描。

硬件连接​

  • 运行前备份 TF 卡数据,按测试项目准备电池、TF 卡、扬声器、USB 设备及通信对端。
  • RS485 / CAN-FD 联合测试依赖按源码帧格式配置的外部转换器:串口帧为 69 字节,CAN-FD 数据为 64 字节;未连接该转换器时,出现联合测试超时应先检查外部测试条件。
  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。

代码​

main/main.c 关键代码
void app_main(void)
{
#if CONFIG_S31_TEST_USB_HOST_ONLY
run_usb_host_only_test();
#else
run_full_test();
#endif
}

代码解释​

  • CONFIG_S31_TEST_USB_HOST_ONLY:控制运行仅 USB Host 日志模式或完整测试模式。
  • run_usb_host_only_test() / run_full_test():分别启动对应测试流程。
  • 通过 idf.py --preview menuconfig 中的 "ESP32-S31 comprehensive test" 选择模式,并配置测试音和 Wi-Fi 扫描。

运行效果​

  • 完整模式显示测试仪表界面;仅 USB Host 模式通过串口输出 USB 日志。
  • 界面的 MANUAL 项需逐项检查测试音、麦克风电平和触摸位置;驱动初始化成功后仍需完成这些检查。


14_lvgl_porting:LVGL 移植​

本示例演示通过 esp_lvgl_adapter 接入 LCD、触摸和背光,运行 LVGL(Light and Versatile Graphics Library)图形动画、控件和性能信息界面。

硬件连接​

  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。
  • 使用板载 LCD 和触摸屏,无需外接显示设备。

代码​

main/main.c 关键代码
esp_lv_adapter_config_t adapter = ESP_LV_ADAPTER_DEFAULT_CONFIG();
adapter.task_priority = 4;
adapter.task_stack_size = 8192;
adapter.tick_period_ms = 5;
ESP_ERROR_CHECK(esp_lv_adapter_init(&adapter));

esp_lv_adapter_display_config_t display_config =
ESP_LV_ADAPTER_DISPLAY_RGB_DEFAULT_CONFIG(lcd->panel_handle, lcd->io_handle,
lcd_config->lcd_width, lcd_config->lcd_height,
ESP_LV_ADAPTER_ROTATE_0);
display_config.profile.buffer_height = 80;
display_config.profile.use_psram = true;
display_config.profile.require_double_buffer = true;
display_config.profile.enable_ppa_accel = CONFIG_S31_LVGL_DEMO_ENABLE_PPA;
display_config.tear_avoid_mode = ESP_LV_ADAPTER_TEAR_AVOID_MODE_DOUBLE_DIRECT;
lv_display_t *display = esp_lv_adapter_register_display(&display_config);
ESP_ERROR_CHECK(display ? ESP_OK : ESP_FAIL);

const esp_lv_adapter_touch_config_t touch_config =
ESP_LV_ADAPTER_TOUCH_DEFAULT_CONFIG(display, touch->touch_handle);
ESP_ERROR_CHECK(esp_lv_adapter_register_touch(&touch_config) ? ESP_OK : ESP_FAIL);
ESP_ERROR_CHECK(esp_lv_adapter_start());

ESP_ERROR_CHECK(esp_lv_adapter_lock(-1));
app_ui_create();
app_ui_start();
esp_lv_adapter_unlock();

代码解释​

  • esp_lv_adapter_init():配置适配层任务优先级、栈和时基。示例使用 LVGL 9.5.0 和 esp_lvgl_adapter 0.6.0。
  • esp_lv_adapter_register_display() / esp_lv_adapter_register_touch():注册 RGB 显示与触摸输入,启用 PSRAM 双缓冲。
  • esp_lv_adapter_start():启动适配层;在适配层锁保护下调用 app_ui_create() 和 app_ui_start() 创建并启动界面。

运行效果​

  • 屏幕显示图形、动画和控件,触摸操作时检查控件响应。
  • 配置菜单中的视频画面由程序生成,格式为 RGB565,默认生成帧率为 30 FPS。


15_bluetooth_speaker:蓝牙音箱​

本示例演示经典蓝牙 A2DP(Advanced Audio Distribution Profile,音频分发协议)音箱,通过 ES8389 输出音频,并提供 LVGL 播放界面。

硬件连接​

  • 断电后连接匹配的扬声器,再通过 Type-C 连接电脑。
  • 准备支持经典蓝牙 A2DP 的手机或其他音源。

代码​

main/main.c 关键代码
void app_main(void)
{
#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE
ESP_ERROR_CHECK(esp_board_manager_init_device_by_name("audio_dac"));
#endif

if (music_ui_start() != ESP_OK) {
ESP_LOGW(BT_AV_TAG, "music UI disabled");
}

ESP_ERROR_CHECK(bredr_app_common_init());


bt_app_task_start_up();
/* bluetooth device name, connection mode and profile set up */
bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL, NULL);

}

代码解释​

  • esp_board_manager_init_device_by_name("audio_dac"):按工程配置初始化板载音频输出。
  • music_ui_start():启动屏幕播放界面;bredr_app_common_init() 初始化经典蓝牙公共配置。
  • bt_app_task_start_up() / bt_app_work_dispatch():启动蓝牙任务并分发协议栈启动事件;默认使用 Bluedroid 和 SBC 解码。

运行效果​

  • 从音源搜索 ESP_SPEAKER 并连接,播放音频,检查扬声器声音与屏幕播放界面。
  • 该示例使用经典蓝牙 A2DP,默认采用 SBC 解码,不提供 BLE 音频或蓝牙串口透传。


16_usb_camera:USB 摄像头​

本示例演示通过 USB Host 采集外接 UVC(USB Video Class)摄像头的 MJPEG 数据,经 JPEG 解码后在 LCD 上预览。

硬件连接​

  • 通过 J3 转接线连接支持匹配 MJPEG 模式的 UVC 摄像头,接线见 USB Host 接线。
  • 使用 USB 数据线将开发板 Type-C 接口连接电脑。本板没有 DVP 摄像头接口。

代码​

main/main.c 关键代码
static esp_err_t open_stream(uvc_host_stream_hdl_t *stream)
{
uvc_host_stream_config_t config = s_stream_config;

for (size_t i = 0; i < sizeof(s_preferred_formats) / sizeof(s_preferred_formats[0]); i++) {
config.vs_format = s_preferred_formats[i];
log_stream_format("Opening UVC stream", &config.vs_format);

esp_err_t ret = uvc_host_stream_open(&config, pdMS_TO_TICKS(5000), stream);
if (ret == ESP_OK) {
return ESP_OK;
}

ESP_LOGW(TAG, "Open candidate %u failed: %s", (unsigned)i, esp_err_to_name(ret));
}

return ESP_ERR_NOT_FOUND;
}

代码解释​

  • app_start():初始化 LCD、帧缓冲、USB Host 与 UVC 驱动,并创建帧处理任务。
  • open_stream() / uvc_host_stream_open():按候选格式尝试打开视频流;源码优先请求 640 × 480、30 FPS,并尝试其他帧率配置。
  • preview_stream():取出帧,调用 draw_camera_frame() 解码并绘制,归还帧缓冲,并周期输出预览 FPS。

运行效果​

  • 摄像头匹配成功后,屏幕显示预览画面;实际选择的格式以摄像头枚举结果和串口日志为准。
  • 请求帧率不等于实测预览帧率,也不代表任意 UVC 摄像头均兼容。



ESP32-S31-Touch-LCD-4.3C Flash 固件的烧录与擦除

ESP32-S31-Touch-LCD-4.3C 提供 16 MiB 出厂合并固件,用于恢复出厂演示。固件文件位于配套仓库的 firmware/ 目录:

项目内容
固件文件ESP32-S31-Touch-LCD-4.3C_FactoryOnly_20261030.bin
烧录地址0x00
下载接口Type-C,经 CH343P 连接 UART0;不使用 J3 USB Host

该出厂固件尚未提供对应源码工程。

数据备份

写入该合并镜像会覆盖应用程序、分区表、设置及数据。操作前备份需要保留的内容。

烧录工具需明确支持 esp32s31,不要选择 esp32s3。如需手动进入下载模式,按以下顺序操作:

  1. 按住 BOOT。
  2. 保持 BOOT 按下,同时按下并松开 RESET。
  3. 松开 BOOT。

烧录完成后,按 RESET 运行固件。

以下步骤适用于烧录本页提供的固件。

  • 下载并解压乐鑫官方烧录工具 Flash Download Tool(下载地址)

  • 运行 Flash Download Tool,根据开发板的主控芯片与下载接口选择对应选项。下图以 ESP32-S3 与 USB 为例,实际选项以产品硬件设计为准


  • 参数设置

    • 选择与开发板所对应的 COM 口
    • 选择 BAUD 为最高的 1152000
    • 点击该行的“...”按钮,选择微雪提供的 bin 文件,并在其右侧手动填写本页上方给出的烧录地址(比如 0x00),同时勾选该行最左侧的复选框
    • 点击 START 开始烧录


  • 等待烧录完成(烧录过程需要一定时间,请耐心等待)

  • 按下复位键,观察运行现象



相关资料

1. 示例程序​

2. 硬件资料​

3. 技术手册​

4. 软件工具​

5. 其他资料​


技术支持

周一-周五(9:30-6:30)周六(9:30-5:30)

手机:13434470212

邮箱:services04@spotpear.cn

QQ:202004841





[教程导航]