从这里开始:对照故障现象
故障现象 | 最可能的原因 | 转到 |
|---|---|---|
I2C 扫描在 0x5D 和 0x14 上均无响应 | 控制器未供电、缺少上拉电阻,或芯片被保持在复位状态 | 第 1 步 |
驱动期望 0x5D 却在 0x14 上发现设备(或相反),或地址在多次启动之间发生变化 | 复位期间 INT 引脚的电平 | 第 2 步 |
设备已被检测到,产品 ID 读取正确,但没有触摸报点 | 状态寄存器未清除、中断边沿配置错误,或 INT 未接线 | 第 3 步 |
有触摸报点,但位置错误、镜像或旋转 | GT911 配置中的分辨率与面板不匹配,或需要交换坐标轴 | 第 4 步 |
打算写入新的配置块 | 请先阅读本节 | 第 5 步 |
按顺序逐步排查。下文的寄存器地址和时序来自 Linux goodix 驱动、Espressif 的 esp_lcd_touch_gt911 组件以及 ESPHome 文档;链接见“参考资料”部分。
1. 确认 GT911 已供电且在 I2C 上应答
供电与上拉电阻
Linux 设备树绑定中为 Goodix 控制器定义了两个电源:AVDD28(模拟电源)和 VDDIO(逻辑 I/O 电源)。在模组或 FPC 上,两者通常都由主机连接器供电,因此应先在连接器处测量电压,再怀疑固件问题。SDA 和 SCL 还需要在总线上某处接上拉电阻;许多显示模组并不自带。
扫描总线
运行 I2C 扫描程序或 i2cdetect。GT911 会在以下两个 7 位地址之一上应答:
7 位地址 | 8 位写/读字节(部分数据手册如此标注) |
|---|---|
| |
| |
8 位地址对来自 Linux 驱动复位代码中的一条注释。如果供应商资料写的是“地址 0xBA”,它与 7 位 0x5D 是同一个设备;在 Arduino、ESP-IDF 和 Linux 中请填写 0x5D。
读取产品 ID
GT911 的寄存器地址为 16 位。Linux 驱动从 0x8140 读取 6 个字节:前 4 个字节是以 ASCII 文本表示的产品 ID,后 2 个字节是固件版本(小端序)。GT911 报告的字符串为 911。如果读到了 911,说明总线、供电和地址都没有问题,问题在排查清单的更后面。
如果两个地址上都无应答,请检查复位线是否被拉低。在许多模组上,RST 是 GT911 的输入引脚,必须由主机驱动为高电平(或在板上加上拉)后控制器才会运行。
2. 正确执行复位与地址选择时序
GT911 在复位释放的瞬间根据 INT 引脚的电平选择其 I2C 地址。用 Linux 绑定的原话说,INT 线“在复位释放时被器件采样,用于选择 I2C 客户端地址”。
RST 变高时 INT 的电平 | I2C 地址 |
|---|---|
低电平 | |
高电平 | |
Linux 驱动所使用的初始化时序
- 将 RST 拉低并等待 10 ms 以上(该驱动等待 20 ms)。
- 将 INT 拉到所选地址对应的电平:
0x14为高电平,0x5D为低电平。 - 等待 100 µs 以上。
- 将 RST 拉高并等待 5 ms 以上(该驱动等待 6–10 ms)。
- 将 INT 拉低保持 50 ms,然后将 INT 切换为输入。
如果在第 4 步期间 INT 处于浮空状态,地址可能在上电之间有所不同。这正是经典的“烧录后正常,冷启动后失效”问题的来源。
ESP-IDF:esp_lcd_touch_gt911
Espressif 的组件将 ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS 定义为 0x5D,将 ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP 定义为 0x14。只有同时满足以下三个条件时,它才会执行地址选择时序:
rst_gpio_num是有效的 GPIO(不是GPIO_NUM_NC),int_gpio_num是有效的 GPIO,driver_data指向一个esp_lcd_touch_io_gt911_config_t,其dev_addr为所需地址。
否则它会打印 I2C address initialization procedure skipped - using default GT9xx setup 并执行普通复位。这种情况下,地址取决于板子的接线,你传入的 I2C panel-IO 地址必须与扫描结果一致。该组件在 ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG() 中默认的 I2C 时钟为 100 kHz。
主机无法控制 INT 的板卡
如果 INT 未连接到主机,主机就无法选择地址,因此应扫描两个地址并使用有应答的那个。例如在 Sunton ESP32-8048S043C 上,GT911 的中断默认未连接到任何 GPIO(参见我们的板卡页面)。ESPHome 的 GT911 页面指出:当 INT 经过 IO 扩展器时,该引脚在启动时仍用于设定地址,但触摸改为轮询方式而非中断驱动。
3. 能检测到设备,但没有触摸事件
读取并清除状态寄存器
触摸数据从 0x814E 开始。第一个字节是状态字节:
- Bit 7(
0x80):缓冲区就绪。只有该位被置位时,新数据才有效。 - Bit 0–3:触摸点数量。Linux 驱动会拒绝超过所配置上限的数量。
- Bit 4:有按键(button)被按下。
每个触摸点占 8 字节:一个 track ID,随后是小端 16 位的 X、Y 和 size。
读取后,Linux 驱动和 esp_lcd_touch_gt911 都会向 0x814E 写入 0。如果自行编写驱动,也应这样做;漏掉该写入是手写驱动只能收到第一次触摸的常见原因。
匹配中断边沿
触发类型存放在 GT911 自身的配置中:0x804D 处配置字节的 bit 0–1(相对配置起始地址 0x8047 的偏移 6)。Linux 驱动按如下方式映射:
数值 | 中断类型 |
|---|---|
0 | 上升沿 |
1 | 下降沿 |
2 | 低电平 |
3 | 高电平 |
GPIO 中断设置需要与之匹配。在 esp_lcd_touch_gt911 中,levels.interrupt = 1 表示上升沿中断,0 表示下降沿。
没有 INT 线?轮询
对 HMI 应用来说,轮询完全够用。未设置 interrupt_pin 时,ESPHome 默认每 50 ms 轮询一次(update_interval)。Linux 驱动在使用中断时,最多会等待 20 ms 的就绪位,超时则放弃该帧。
4. 触点位置不对
检查 GT911 中保存的分辨率
GT911 上报的坐标是其配置中写入的分辨率,而不是你显示屏的分辨率。根据 Linux 驱动,X 最大值是 0x8048 处的小端 16 位值,Y 最大值在 0x804A。读出这两个值。如果控制器配置为 1024×600 而你的面板是 800×480,触点会落在手指的右下方,且远离手指的边缘区域会超出屏幕。解决办法是做缩放(或把驱动的限值设置为控制器的值)。
各软件栈的限值来源:
软件栈 | 分辨率来源 | 交换与镜像 |
|---|---|---|
Linux | 从 GT911 配置中读取;配置中没有时回退为 4095 × 4095 | 设备树属性 |
ESP-IDF | | |
ESPHome | 触摸屏 | |
从原始值开始校准
ESPHome 的触摸屏页面建议在 on_touch lambda 中记录 touch.x_raw 和 touch.y_raw,多次触碰屏幕边缘像素处的四个角,然后把原始值的最小值和最大值填入校准参数。同样的方法适用于任何平台:打印原始 X 和 Y,触碰四个角,再把量程映射到屏幕上。
按以下顺序修正方向:先把 X 和 Y 调到正确的轴上(swap_xy),再翻转方向反了的轴(mirror_x / mirror_y)。显示屏的逻辑 (0, 0) 必须位于左上角。
5. 重写 GT911 配置:最后手段
配置块从 0x8047 开始。对 GT911,Linux 驱动将其视为 186 字节:
- 字节 0(
0x8047):配置版本。 - 字节 1–4:X 和 Y 分辨率(见第 4 步)。
- 字节 5(
0x804C):最大触点数,低 4 位。 - 字节 6(
0x804D):中断触发类型,低 2 位。 - 字节 184(
0x80FF):校验和,即字节 0–183 之和的 8 位二进制补码。 - 字节 185(
0x8100):config_fresh,必须为1。
Linux 驱动本身只有在同时拥有 INT 和 RST GPIO 并找到固件文件(默认文件名 goodix_911_cfg.bin,或 goodix,config-name 属性指定的名称)时才会写入配置。没有该文件时,它使用芯片中已存储的配置。
在写入任何内容之前,先读出全部 186 字节并保存。能在软件层面解决的分辨率和方向问题,尽量在软件中解决。为其他触摸面板制作的配置块可能导致你的面板触摸失效,所以如果确实需要修改,请向面板供应商索取配置文件。
如何选择电容触摸模块
如果你要为新设计选购 CTP 显示屏,下单样品前请向供应商确认三件事:采用的触摸控制器型号、出厂默认的 I2C 地址,以及 INT 和 RST 是否引出到连接器。把你的尺寸、接口和主控处理器通过 Ask an Engineer 发给我们,我们会连同这三项答案一起推荐合适的模块。
常见问题
GT911 的 I2C 地址是多少?
0x5D 或 0x14(7 位地址)。控制器在复位释放时采样 INT 引脚电平:INT 为低电平选择 0x5D,INT 为高电平选择 0x14。有些数据手册列出 0xBA/0xBB 或 0x28/0x29,那是同一地址的 8 位写/读字节形式。
为什么我的 GT911 重启后地址会变?
复位释放时 INT 引脚悬空或被其他器件驱动,导致控制器每次采样到不同的电平。在释放 RST 之前将 INT 拉低(对应 0x5D)或拉高(对应 0x14),等待 5 ms 以上,将 INT 保持低电平 50 ms,然后将其设为输入。如果主机无法控制 INT,则同时扫描两个地址。
为什么 GT911 只响应一次触摸?
读取 0x814E 处的触摸数据后,向 0x814E 写入 0。Linux 的 goodix 驱动和乐鑫的 esp_lcd_touch_gt911 都会在每次读取后执行此操作;跳过这一步的驱动通常会再也检测不到新的触摸。
为什么 GT911 的触摸坐标被缩放或偏移?
GT911 按其自身配置中存储的分辨率上报坐标(X 在 0x8048,Y 在 0x804A)。如果与您的面板分辨率不一致,请对数值进行缩放,或将驱动的 x_max/y_max 设为控制器的分辨率,再通过 swap_xy 和 mirror_x/mirror_y 调整方向。
GT911 不接 INT 引脚能工作吗?
可以。改为轮询 0x814E 状态寄存器,而不使用中断。ESPHome 在未设置 interrupt_pin 时默认每 50 ms 轮询一次。没有 INT 时主机也无法选择地址,因此使用 0x5D 或 0x14 中有应答的那个即可。
我应该重写 GT911 的配置吗?
仅作为最后手段。先从 0x8047 读出并保存现有的 186 字节配置块;优先在软件中修正分辨率和方向;如确需写入配置,请使用触摸屏供应商提供的配置文件。该配置块末尾是位于 0x80FF 的 8 位校验和,以及位于 0x8100、必须为 1 的 config_fresh 字节。