RIOT 支持 LILYGO TTGO T8 ESP32-S2 开发板:外设配置、GPIO 映射与烧录实战
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
LILYGO TTGO T8(又称 LilyGo T-Display S2)是一块集成 1.9 英寸 ST7789 OLED 显示屏与 TF 卡槽的 ESP32-S2 开发板。本文以 RIOT 仓库中该板卡的 doc.md 为骨架,结合 periph_conf.h、board.h 与 Makefile/Kconfig 源码,系统讲解该板卡在 RIOT 中的特性、默认 GPIO 分配、外设配置细节以及两种 USB 模式下的烧录方法,帮助你在 RIOT 中快速启用这块板卡并编写驱动 OLED 与 SD 卡的应用程序。
板卡概览与主要特性
Espressif LILYGO TTGO T8 ESP32-S2 是 ESP32-S2 系列的典型开发板,核心卖点是一块 240×135 的 ST7789 OLED 显示屏和一个 TF(microSD)卡槽。RIOT 官方为其提供了完整板卡支持,板卡目录位于boards/esp32s2-lilygo-ttgo-t8,其doc.md中给出的主要特性如下:
| 特性 | 支持情况 |
|---|---|
| ESP32-S2 SoC | 支持 |
| 4 MB Flash | 支持 |
| 8 MB QSPI RAM | 支持 |
| SD 卡槽 | 支持 |
| 32.768 kHz 晶振 | 支持 |
| ST7789 OLED 显示屏 | 支持 |
板卡目录的 Makefile.features 进一步印证了这些特性:板卡使用CPU_MODEL = esp32s2,并对外提供esp_spi_ram(外部 8 MB QSPI PSRAM)、periph_adc、periph_dac、periph_i2c、periph_pwm、periph_spi、periph_usbdev、sdcard_spi、tinyusb_device以及esp_rtc_timer_32k等特性;同时板卡还支持完整的 Arduino 适配层(arduino_analog、arduino_i2c、arduino_pins、arduino_pwm、arduino_spi、arduino_uart、arduino_dac),意味着可以直接使用 RIOT 的 Arduino API 编写应用。
MCU
板卡绝大部分功能由 ESP32-S2 SoC 提供。ESP32-S2 属于 ESP32x SoC 家族,包含 2 个 UART(板卡仅使用 UART_DEV(0))、1 个 USB OTG 接口(GPIO19/GPIO20)、多路 ADC/DAC 等外设。关于 ESP32-S2 SoC 系列(family)的详细说明,可参考 RIOT CPU 目录下 ESP32 系列文档(cpu/esp32与 cpu/esp_common 中的相关实现),本文聚焦于该板卡特有的板级配置。
板级默认配置(Board Configuration)
TTGO T8 的板级配置有几个关键决策点:两路 SPI 的用途划分、USB 信号的 DIP 开关切换、以及 32.768 kHz 晶振的 DIP 开关切换。
SPI 资源划分
- SPI_DEV(0)(FSPI)专用于 OLED 显示屏:其 GPIO 未引出到排针,不能被其他设备复用;
- SPI_DEV(1) 专用于 SD 卡槽:其 GPIO 均已引出,可以同时被其他 SPI 设备使用。
在 periph_conf.h 中,SPI_DEV(0) 使用 FSPI(SPI Controller 2),SPI_DEV(1) 使用 HSPI(SPI Controller 3)。需要注意:这些 GPIO 只有在对应 SPI 接口首次被spi_init_cs或spi_acquire调用时才会被初始化为 SPI 信号,之前完全可作他用。
USB 信号切换(DIP 开关)
板载 USB-to-UART 桥,USB-C 接口的 D-/D+ 信号通过 DIP 开关决定连接到哪一端:
- 默认:连接到板载 USB-to-UART 桥,自带复位/烧录/下载逻辑,可直接用于串口控制台与烧录;
- 切换到 GPIO19 / GPIO20:此时启用 ESP32-S2 自带的 USB OTG 接口,若仍希望通过 USB 查看控制台输出,需要启用
stdio_cdc_acm或stdio_tinyusb_cdc_acm模块(当使用 USBUS 或 tinyUSB 协议栈时会自动启用)。
32.768 kHz 晶振切换(DIP 开关)
板载 32.768 kHz 晶振默认通过 DIP 开关连接到 GPIO15 与 GPIO16。关闭 DIP 开关后,这两个引脚才会在排针上可用(例如用作 PWM_DEV(1) 的通道)。
默认 GPIO 分配表
doc.md 给出的默认板级配置按 GPIO 功能排序如下(该配置可被"应用特定配置"覆盖,见下文说明):
| 功能 | GPIO | 备注 | 配置参考 |
|---|---|---|---|
| BUTTON0 | GPIO0 | BOOT 按键 | — |
| ADC_LINE(n) | GPIO1 … GPIO9 | ADC 通道 | ESP32 ADC Channels |
| DAC_LINE(n) | GPIO17, GPIO18 | DAC 通道 | ESP32 DAC Channels |
| GPIO38 | GPIO38 | OLED RESET(未引出) | — |
| I2C_DEV(0) SCL | GPIO7 | ESP32 I2C Interfaces | |
| I2C_DEV(0) SDA | GPIO8 | ESP32 I2C Interfaces | |
| PWM_DEV(0) | GPIO39, GPIO40, GPIO41, GPIO42 | ESP32 PWM Channels | |
| PWM_DEV(1) | GPIO15, GPIO16 | 未使用esp_rtc_timer_32k时可用 | ESP32 PWM Channels |
| SPI_DEV(0) CLK | GPIO36 | OLED CLK(未引出) | |
| SPI_DEV(0) MISO | GPIO9 | FSPIHD 哑元(未引出),GPIO37 用作 DCX | |
| SPI_DEV(0) MOSI | GPIO35 | OLED MOSI(未引出) | |
| SPI_DEV(0) CS0 | GPIO34 | OLED CS0(未引出) | |
| SPI_DEV(1) CLK | GPIO12 | SD 卡 CLK | ESP32 SPI Interfaces |
| SPI_DEV(1) MISO | GPIO13 | SD 卡 MISO | ESP32 SPI Interfaces |
| SPI_DEV(1) MOSI | GPIO11 | SD 卡 MOSI | ESP32 SPI Interfaces |
| SPI_DEV(1) CS0 | GPIO10 | SD 卡 CS | ESP32 SPI Interfaces |
| UART_DEV(0) TxD | GPIO43 | 控制台 | ESP32 UART Interfaces |
| UART_DEV(0) RxD | GPIO44 | 控制台 | ESP32 UART Interfaces |
| USB D- | GPIO19 | 未使用 USB-to-UART 桥时 | |
| USB D+ | GPIO20 | 未使用 USB-to-UART 桥时 |
说明:上表中 SPI_DEV(1) 的 MISO/MOSI/CS0 引脚号以 periph_conf.h 中的实际定义(GPIO13 / GPIO11 / GPIO10)为准,这是板卡当前生效的配置;
doc.md中的表格在这些引脚上与源码存在出入,实际接线请以源码为准。SPI_DEV(0) 的 MISO 在doc.md表格中标为 GPIO37,而 periph_conf.h 中SPI0_MISO定义为 GPIO9(FSPIHD 哑元),因为 GPIO37 实际被用作 OLED 的 DCX 信号。
关于外设配置的通用细节(ADC 通道编号、I2C/SPI 接口编号、PWM 通道映射等),参见 ESP32 板卡的 Common Peripherals 章节(cpu/esp32与boards/common/esp32s2中提供公共定义)。
外设配置源码深度解读
ADC 与 DAC
periph_conf.h 定义了:
ADC_GPIOS = { GPIO1, GPIO2, GPIO4, GPIO5, GPIO6, GPIO7, GPIO8, GPIO9 }:ADC1 上所有引出的引脚都被声明为 ADC 通道,GPIO3 因是 strapping 引脚被排除;GPIO7/GPIO8 在启用 I2C_DEV(0) 时会被 I2C 占用;GPIO9 未引出,用于测量 V_BAT;DAC_GPIOS = { GPIO17, GPIO18 }:两个 DAC 通道。
源码注释特别强调:这些 GPIO 只有在通过adc_init/dac_init初始化为 ADC/DAC 通道之后才被占用,在此之前可用于其他用途。
I2C
板卡仅定义一个 I2C 接口I2C_DEV(0):
I2C0_SPEED = I2C_SPEED_FAST(快速模式);I2C0_SCL = GPIO7,I2C0_SDA = GPIO8。
同样,只有在使用periph_i2c模块时这些 GPIO 才会被初始化为 I2C 信号。
PWM
板卡配置了两个 PWM 设备,包含了未定义为 I2C/SPI/UART 的所有输出引脚:
PWM_DEV(0):PWM0_GPIOS = { GPIO39, GPIO40, GPIO41, GPIO42 };PWM_DEV(1):PWM1_GPIOS = { GPIO15, GPIO16 },但仅在未启用esp_rtc_timer_32k模块时定义(因为此时 GPIO15/GPIO16 被 32.768 kHz 晶振占用)。
SPI 与 ST7789 OLED、SD 卡
SPI 配置与板级功能一一对应:
- SPI_DEV(0)(FSPI):SCK=GPIO36、MISO=GPIO9(哑元)、MOSI=GPIO35、CS0=GPIO34,专用于 OLED;
- SPI_DEV(1)(HSPI):SCK=GPIO12、MISO=GPIO13、MOSI=GPIO11、CS0=GPIO10,用于 SD 卡。
在 board.h 中,OLED 与 SD 卡的外设参数被进一步细化:
ST7789 OLED 参数(启用st7789模块时生效):
#define ST77XX_PARAM_CNTRL ST77XX_CNTRL_ST7789 // ST7789 控制器 #define ST77XX_PARAM_SPI SPI_DEV(0) // SPI 设备 #define ST77XX_PARAM_SPI_CLK SPI_CLK_10MHZ // SPI 时钟 10 MHz #define ST77XX_PARAM_SPI_MODE SPI_MODE_0 #define ST77XX_PARAM_CS GPIO34 // 片选 #define ST77XX_PARAM_DCX GPIO37 // DCX 引脚 #define ST77XX_PARAM_RST GPIO38 // 复位引脚 #define ST77XX_PARAM_RGB 1 // RGB 模式 #define ST77XX_PARAM_INVERTED 1 // 反色显示 #define ST77XX_PARAM_NUM_LINES 240U // 行数(高) #define ST77XX_PARAM_RGB_CHANNELS 135U // 列数(宽) #define ST77XX_PARAM_ROTATION ST77XX_ROTATION_270 // 旋转 270° #define ST77XX_PARAM_OFFSET_X 40 // X 偏移 #define ST77XX_PARAM_OFFSET_Y 52 // Y 偏移即这是一块240×135的 ST7789 屏幕,RIOT 默认旋转 270° 并设置 40/52 的偏移来对齐显示区域。GPIO37 在此处扮演 DCX 角色,这也是 SPI_DEV(0) 的 MISO 在源码中被置为哑元 GPIO9 的原因。
背光控制:
#define BACKLIGHT_PIN GPIO33 // 背光引脚 #define BACKLIGHT_ON gpio_set(BACKLIGHT_PIN) #define BACKLIGHT_OFF gpio_clear(BACKLIGHT_PIN)board.c 中的board_init会在启用st77xx模块时把背光引脚初始化为输出。
SD 卡参数(启用sdcard_spi模块时生效):
#define SDCARD_SPI_PARAM_SPI SPI_DEV(1) #define SDCARD_SPI_PARAM_CS SPI1_CS0 // GPIO10 #define SDCARD_SPI_PARAM_CLK SPI1_SCK // GPIO12 #define SDCARD_SPI_PARAM_MOSI SPI1_MOSI // GPIO11 #define SDCARD_SPI_PARAM_MISO SPI1_MISO // GPIO13 #define SDCARD_SPI_PARAM_POWER GPIO_UNDEF // 无电源控制引脚依赖自动装配(Makefile.dep):
- 启用
mtd模块 → 自动加入mtd_sdcard_default; - 启用
vfs_default→ 自动加入fatfs_vfs与mtd(默认在 SD 卡上使用 FAT 文件系统); - 启用
disp_dev→ 自动加入st7789; - 启用
saul_default→ 自动加入saul_gpio(SAUL 直接映射 GPIO)。
也就是说,在应用 Makefile 中只需声明USEMODULE += vfs_default或USEMODULE += disp_dev,SD 卡文件系统与 OLED 显示驱动就会被自动拉起。
按键(BUTTON0 / BOOT)
board.h 定义:
BTN0_PIN = GPIO0:板上的 BOOT 按键在正常运行时可作为用户按键;BTN0_MODE = GPIO_IN_PU:按键 GPIO 已被外部上拉电阻上拉,模式需为输入上拉,按下时信号为低;BTN0_INT_FLANK = GPIO_FALLING:默认下降沿触发中断。
gpio_params.h 中将其注册进 SAUL:
static const saul_gpio_params_t saul_gpio_params[] = { { .name = "BOOT", .pin = BTN0_PIN, .mode = BTN0_MODE, .flags = SAUL_GPIO_INVERTED }, };启用saul_default后,应用即可通过 SAUL API 读取按键状态。
UART 控制台
UART_DEV(0) 使用固定标准配置,且引脚不可更改:
UART0_TXD = GPIO43,UART0_RXD = GPIO44。
编译与烧录(Flashing the Device)
板卡通过 USB-C 接口供电与通信,烧录方式取决于 DIP 开关的当前配置。
方式一:USB-C 连接 USB-to-UART 桥(默认)
这是默认出厂配置,自带复位/烧录/下载逻辑,操作最简单:把板卡连到主机,使用编程端口直接烧录:
BOARD=esp32s2-lilygo-ttgo-t8 make flash方式二:USB-C 连接 ESP32-S2 的 USB 信号
将 DIP 开关切换到 GPIO19/GPIO20 后,可使用 SoC 内置的 USB-to-JTAG 桥烧录。USB-to-JTAG 桥会在 bootloader 的下载模式下自动激活,前提是 eFuseJTAG_SEL_ENABLE与DIS_USB_JTAG未被烧写(参见 JTAG Interface 中 strapping 引脚 GPIO3 的说明)。
连接板卡后,通过编程端口执行(需同时启用esp32s2-lilygo-ttgo-t8-usb伪模块,该模块会通过 Makefile.include 自动把PORT_LINUX设为/dev/ttyACM0,并自动引入stdio_cdc_acm依赖):
USEMODULE=esp32s2-lilygo-ttgo-t8-usb BOARD=esp32s2-lilygo-ttgo-t8 make flash如果 RIOT 已经在设备上运行,该命令通常会自动复位设备并进入 bootloader 下载模式。若遇到以下情况:
- RIOT 尚未烧录到设备;
- 自动复位失效;
- 设备卡在其他模式;
则需要手动强制进入下载模式:按住 BOOT(BOT)按键的同时按一下 RST 复位按键,然后再执行烧录命令。
Kconfig 中的对应开关
板卡配置同时暴露了 Kconfig 入口(Kconfig):
ESP32S2_LILYGO_TTGO_T8_USB:勾选表示使用 USB 接口而非 USB-to-UART 桥(需配合 DIP 开关切换);ESP32S2_LILYGO_TTGO_T8_32K_XTAL(默认开启):表示使用板载 32.768 kHz 晶振;若在排针上使用 GPIO15/GPIO16,应关闭该选项,从而释放这两个引脚给 PWM_DEV(1)。
串口自动识别过滤
Makefile.include 中还配置了 TTY 自动选择过滤规则:
TTY_BOARD_FILTER := --driver 'ch341' --vendor '1a86' --model 'USB Serial'即板载 USB-to-UART 桥使用 CH341 芯片(vendor 1a86),配合MOST_RECENT_PORT=1时 RIOT 会自动匹配该串口设备。
应用示例要点
在 RIOT 中开发 TTGO T8 应用时,建议按需组合以下模块:
# 最小控制台 + OLED USEMODULE += disp_dev # 自动引入 st7789,板级参数自动生效 # SD 卡文件系统 USEMODULE += vfs_default # 自动引入 fatfs_vfs + mtd(mtd_sdcard_default) # USB OTG 作为控制台(需 DIP 切到 USB 模式) USEMODULE += esp32s2-lilygo-ttgo-t8-usb # SAUL 感知层(读取 BOOT 按键等) USEMODULE += saul_default得益于 board.h 中的默认参数,ST7789 的disp_dev接口与 SD 卡的mtd/vfs接口无需手动指定引脚,开箱即用;板卡排针上引出的 GPIO1–GPIO9(ADC)、GPIO17/18(DAC)、GPIO7/8(I2C)、GPIO39–42(PWM)则可通过 RIOT 的periph_*API 直接操作,具体接口编号可对照上文 GPIO 分配表。
总结
LILYGO TTGO T8 ESP32-S2 是 RIOT 中一块"开箱即用"程度很高的 ESP32-S2 板卡:OLED(SPI_DEV(0)/ST7789)与 SD 卡(SPI_DEV(1)/FATFS)的板级参数已在 board.h 与 periph_conf.h 中完整定义,烧录只需在默认 DIP 配置下执行BOARD=esp32s2-lilygo-ttgo-t8 make flash;切换到 USB OTG 模式时则需启用esp32s2-lilygo-ttgo-t8-usb伪模块并配合 GPIO19/20 的 DIP 开关。理解 DIP 开关(USB 信号、32.768 kHz 晶振)与源码中 GPIO 分配之间的对应关系,是高效使用这块板卡的关键。
【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考