ESP32-2432S028 (CYD 2.8寸黄屏) · CN1接口 · 万能I2C测试工具

ESP32黄屏 万能IIC测试仪
资料(CN1一键扫描测试)

CN1排针插上任意I2C模块,屏幕自动扫描地址、判断在不在线,QUICK模式秒出结果,FULL模式 跑稳定性/自检。目的是在写这个模块专属代码之前,先用一个通用工具确认"模块+接线+供电" 这条链路没问题——省得排查时分不清是代码bug还是硬件没接对。

整理于 2026-08-07 · 已实机烧录测试,CN1先后接过 SCD41、BNO055、DPS310

  • 主控ESP32-2432S028 (CYD)
  • 屏幕2.8寸 ST7789 240×320
  • 触摸XPT2046 电阻触摸
  • 接口CN1 (GND/IO22/IO27/3V3)
  • 专属协议支持Sensirion SGP4x / VL53L5CX
  • 看门狗esp_task_wdt 4s
当前状态
固件编译已完成
真机烧录测试已实测
CN1接SCD41验证已实测
CN1接BNO055验证已实测
CN1接DPS310验证已实测
实拍图 / 接线照片部分补充(BNO055已有)
1

这是什么

这是一个跑在 ESP32-2432S028(俗称 CYD,Cheap Yellow Display,2.8寸黄屏)上的通用 I2C 测试工具:CN1 排针插上任意一个 I2C 模块,固件自动扫描 1~126 全部地址,找到就报告地址、 判断在不在线;再按一下屏幕上的 FULL 按钮,对已知协议的芯片(目前是 Sensirion SGP4x 系列和 VL53L5CX)跑真实的自检/测距,对其它芯片做通用的读数稳定性检测。

写这个工具的目的不是替代每个模块专属的测试代码,而是在写那份代码之前先有一个"总线通不通、 模块在不在线"的快速判断——不然排查的时候经常分不清到底是自己代码写错了,还是模块根本没接对 或者没通电。

跟站内其它几篇资料共用同一块板子和同一个接口

CN1 排针(GND-IO22-IO27-3V3,IO22当SCL、IO27当SDA)是本站 SCD41、BNO055、 DPS310 几篇资料里用来接 I2C 模块的同一个接口, 同一块 CYD 板子换着接不同模块。这个万能测试仪就是从反复排查这几个模块的经验里抽出来的通用工具。

2

硬件与CN1接口说明

主控板关键参数

项目说明
主控ESP32-2432S028R (CYD),ESP32-D0WD-V3 双核
屏幕2.8寸 ST7789 驱动 TFT,240×320,本项目位带(bit-bang)直接操作GPIO寄存器手写驱动,不依赖 TFT_eSPI 库
触摸XPT2046 电阻触摸,SPI软件位带读取
Flash / 分区4MB Flash,huge_app 分区方案(3MB APP,无OTA)

CN1 扩展口 —— I2C 接口

  • GND地
  • IO22本项目当 SCL(I2C时钟)用
  • IO27本项目当 SDA(I2C数据)用
  • 3V33.3V 供电
同一时间只能接一个模块

IO22/IO27 是通用 GPIO 复用出来的 I2C,不是独立走线——同一时间 CN1 上只能接一个 I2C 模块,换模块前先拔掉旧的,两个模块的地址一样也无法同时挂在总线上分辨。

LCD / 触摸引脚定义(源码 ESP32_2432S028_Universal_I2C_Tester.ino 第10-27行)

ESP32_2432S028_Universal_I2C_Tester.ino:10
// ESP32-2432S028 / CYD 2.8 inch ST7789 internal LCD pins.
#define PIN_SCK  14
#define PIN_SDA  13
#define PIN_CS   15
#define PIN_RST  -1
#define PIN_DC   2
#define PIN_BLK  21

// CN1 sensor header: GND - IO22 - IO27 - 3V3. Any I2C device can go here.
#define I2C_SDA 27
#define I2C_SCL 22

// ESP32-2432S028R resistive touch controller, usually XPT2046.
#define TOUCH_CS   33
#define TOUCH_IRQ  36
#define TOUCH_MOSI 32
#define TOUCH_MISO 39
#define TOUCH_SCLK 25
3

已验证测试过的模块

CN1 先后接过下面三个模块验证,固件都能正常识别地址、QUICK/FULL 两个模式都测过:

CO2传感器

SCD41

Sensirion CO2传感器,本资料库有独立的完整技术资料页(含实拍图、接线、CO2实测数据)。

九轴传感器

BNO055

九轴绝对方向传感器,本资料库有独立的完整技术资料页。

气压/高度传感器

DPS310

精密气压高度传感器,本资料库有独立的完整技术资料页,同样接在CN1上测试过。

CN1接BNO055实测截图,屏幕显示I2C QUICK模式OK,ADDR 0x28
实拍:CN1接BNO055,QUICK模式秒出结果——OK / ADDR 0x28, 跟BNO055真实I2C地址(0x28,ADR脚接地时)完全对上。
诚实说明:FULL模式对这三个模块跑的是通用分支,不是专属读数

固件目前只对两类芯片写了专属协议支持:0x59 地址的 Sensirion SGP4x 系列(自检+序列号+VOC/NOx)和 VL53L5CX(真实 ToF 测距)。SCD41、BNO055、DPS310 都不在这个专属列表里,FULL 模式对它们走的是通用分支——只读4字节原始数据看 稳不稳定、抖不抖,不解析成 CO2 浓度 / 姿态角 / 气压这些真实物理量。这个工具 验证的是"总线和接线没问题",真实读数请看各自模块的专属资料页。

4

QUICK / FULL 两种测试模式

模式行为适用场景
QUICK只发 Wire.beginTransmission/endTransmission 探测有没有 ACK,秒级出结果,屏幕显示地址和累计连接次数插上模块先看一眼有没有反应,最快的第一道检查
FULLSGP4x:真实自检(0x280E)+读序列号(0x3682)+持续测VOC/NOx;VL53L5CX:begin()上传固件+8x8测距,报告中心/角落两点距离;其它设备:连续读4字节原始数据,记录最大抖动(delta),抖动小于阈值且采样数够才判 PASS确认模块不只是"有反应",而是能持续稳定工作

FULL 模式的判定阈值由源码里的 TEST_MODE 宏切换,当前编译用的是宽松档 MODE_QUICK(8秒预热、连续4次采样、抖动阈值1000才算稳定),源码里还留了更严格的 MODE_LABEL 档(30秒预热、15次采样、阈值500),改一行宏定义重新编译即可切换成 更严苛的产线级判定。

5

触屏操作说明

屏幕底部固定4个触摸按钮,从左到右:

  • IIC切到 QUICK 模式
  • FULL切到 FULL 模式
  • CLR清零连接计数;长按(≥1秒)在任意界面都能清零,不用先切到这个按钮所在的界面
  • RFSH强制刷新一次(重新走一遍总线恢复+地址扫描)
代码里的一个真实细节

触摸屏的原始X坐标是反的(数值越大,物理位置越靠屏幕左边), 所以四个按钮的判断阈值是从右往左递减的,源码 handleTouch() 里专门写了注释说明这一点, 照抄这段逻辑时注意别把方向搞反。

6

固件源码关键段

下面三段是源码里带真实排查经验的关键逻辑,摘自 ESP32_2432S028_Universal_I2C_Tester.ino。

① I2C 总线卡死自动恢复(第296-326行)

某个模块半途掉线可能把 SDA 拉死在低电平,堵死总线上所有其它设备。标准做法是手动打 最多9个SCL时钟把卡住的从机"放行",再补一个手动STOP让总线回到idle。

ESP32_2432S028_Universal_I2C_Tester.ino:301
// Standard I2C bus recovery: a device that got interrupted mid-byte can
// hold SDA low forever and jam the whole bus for every other device on it.
// Clocking SCL up to 9 times lets a stuck slave finish/release SDA, then a
// manual STOP condition puts the bus back to idle. Cheap to call any time
// (returns almost instantly) since it exits immediately once SDA is high.
static void recoverBus() {
  Wire.end();
  pinMode(I2C_SDA, INPUT_PULLUP);
  pinMode(I2C_SCL, OUTPUT);
  digitalWrite(I2C_SCL, HIGH);
  delayMicroseconds(5);
  for (uint8_t i = 0; i < 9 && !digitalRead(I2C_SDA); i++) {
    digitalWrite(I2C_SCL, LOW);
    delayMicroseconds(5);
    digitalWrite(I2C_SCL, HIGH);
    delayMicroseconds(5);
  }
  pinMode(I2C_SDA, OUTPUT);
  digitalWrite(I2C_SDA, LOW);
  delayMicroseconds(5);
  digitalWrite(I2C_SCL, LOW);
  delayMicroseconds(5);
  digitalWrite(I2C_SCL, HIGH);
  delayMicroseconds(5);
  digitalWrite(I2C_SDA, HIGH);
  delayMicroseconds(5);
  Wire.begin(I2C_SDA, I2C_SCL);
  Wire.setClock(100000);
  Wire.setTimeOut(8);
  delay(5);
}

② 地址扫描去抖:先扫到,等30ms,再扫一次确认(第541-573行)

刚插上的连接器可能瞬间接触不良发生跳动,模块刚上电那几毫秒也可能误应答错误地址。 直接认第一次扫到的结果不可靠,所以扫到候选地址后先等待再复扫一次,两次一致才真正采信。

ESP32_2432S028_Universal_I2C_Tester.ino:556
// A freshly-mated connector can bounce, and a module mid power-on can
// glitch-ACK the wrong address for a few ms. Don't latch on the first
// hit alone: let it settle, then re-scan and only commit if the same
// address confirms. This is what "first read shows the wrong address,
// retesting fixes it" was — nothing wrong with the module, we were just
// reading before the bus/power had settled.
delay(30);
for (uint8_t addr = 1; addr < 127; addr++) {
  if (probeAddress(addr) == 0) {
    if (addr == candidate) {
      activeAddr = addr;
      return true;
    }
    return false;
  }
}
return false;

③ VL53L5CX 初始化让出看门狗(第759-769行)

VL53L5CX 的 begin() 要通过I2C往传感器里上传约80KB固件,正常情况下要跑好几秒, 比看门狗4秒的超时还长——如果不处理,这一步会被硬件看门狗误判成"卡死"直接强制重启。

ESP32_2432S028_Universal_I2C_Tester.ino:759
drawTextBg(12, 66, "TOF INIT", YELLOW, BLACK, 3);
// begin() uploads ~80KB of firmware into the sensor over I2C and can
// legitimately take several seconds — pull the loop task off the
// watchdog for just this one call so that doesn't look like a hang.
esp_task_wdt_delete(NULL);
bool tofOk = vl53l5cx.begin(VL53L5CX_ADDR, &Wire, 400000) &&
             vl53l5cx.setResolution(64) &&
             vl53l5cx.setRangingFrequency(15) &&
             vl53l5cx.startRanging();
esp_task_wdt_add(NULL);
7

固件下载与编译

⬇ 下载 .ino 源文件 ⬇ 下载源码包(.ino + zh_bitmap.h)

编译参数取值
开发板esp32:esp32:esp32
Partition Schemehuge_app
依赖库Adafruit VL53L5CX(会自动带上 Adafruit BusIO 依赖);其余用的 Wire.h/esp_task_wdt.h 是核心自带
编译结果程序 427890 字节(13%),全局变量 25080 字节(7%),Arduino-CLI + ESP32 core 3.2.1 本地编译通过,无报错
8

网页烧录流程

不用装 Arduino IDE,浏览器直接烧录,用的是乐鑫官方真正的 ESP Launchpad (espressif/esp-launchpad, 开源),不是自制的简易版工具——本站把编译好的固件放在自己服务器上,配一个官方支持的 launchpad.toml 配置文件指过去,打开链接就是官方页面的 Quick Start 一键烧录模式。

🔥 打开 ESP Launchpad 一键烧录

  1. 用数据线把 ESP32-2432S028 接上电脑(需要 Chrome / Edge 等支持 Web Serial 的浏览器)。
  2. 点上面的按钮,打开的页面会直接显示本项目固件卡片(Quick Start 模式)。
  3. 点 Connect,在弹出的串口列表里选中开发板对应的串口。
  4. 点 Flash 开始烧录,进度条走完即完成,设备会自动重启。
备选:DIY 模式手动烧录

如果 flashConfigURL 一键卡片加载不出来(比如网络问题),可以退到 手动模式:打开 ESP Launchpad 官方首页, 切到 DIY 标签,Flash Address 保持默认 0,选择文件下载 merged bin 固件 (已经是 bootloader+分区表+程序合并好的单文件,约4MB),其余步骤跟 Quick Start 一样。

9

常见问题与避坑

现象说明 / 排查方向
屏幕显示 BUS LOWSDA或SCL被拉死在低电平,固件会自动跑一次 recoverBus() 恢复;持续报错先查排线有没有短路
屏幕显示 NO RESPONSE没插好、没通电、芯片本身坏了,这三种情况I2C协议本身分辨不出来,工具只能告诉你"没应答",不能告诉你具体哪种
FULL模式对我的模块显示的数字看不懂含义如果不是SGP4x或VL53L5CX,FULL模式走的是通用4字节读数,不代表真实物理量(见第3节说明)
换了个模块要不要重新烧录固件不用,固件本身是通用的,拔掉旧模块插新模块,屏幕会自动重新扫描识别
ESP Launchpad 一键卡片打不开/加载慢退到 DIY 手动模式,见第8节备选方案
10

参考资料

本页固件已实机烧录测试,CN1接口先后验证过SCD41、BNO055、DPS310三个模块(用户原话)。 BNO055的实测截图已补充(第3节),SCD41/DPS310的实拍图还在补充中。

← 返回显示与LED分类 返回首页 进入淘宝店铺 →