Start here: match the symptom
Symptom | Most likely cause | Go to |
|---|---|---|
Nothing at 0x5D or 0x14 on an I2C scan | No power to the controller, missing pull-ups, or the chip is held in reset | Step 1 |
Found at 0x14 when the driver expects 0x5D (or the other way round), or the address changes between boots | INT pin level during reset | Step 2 |
Detected, product ID reads correctly, but no touches arrive | Status register not cleared, interrupt edge wrong, or INT not wired | Step 3 |
Touches arrive but land in the wrong place, mirrored or rotated | Resolution in the GT911 config doesn't match the panel, or axes need swapping | Step 4 |
Tempted to write a new config block | Read this first | Step 5 |
Work through the steps in order. The register addresses and timings below come from the Linux goodix driver, Espressif's esp_lcd_touch_gt911 component and the ESPHome documentation; links are in the Sources section.
1. Confirm the GT911 is powered and answering on I2C
Power and pull-ups
The Linux device-tree binding for Goodix controllers names two supplies: AVDD28 (analog) and VDDIO (the logic I/O rail). On a module or FPC both are usually fed from the host connector, so measure them at the connector before suspecting firmware. SDA and SCL also need pull-up resistors somewhere on the bus; many display modules don't include them.
Scan the bus
Run an I2C scanner sketch or i2cdetect. A GT911 answers at one of two 7-bit addresses:
7-bit address | 8-bit write / read bytes (as some datasheets list them) |
|---|---|
| |
| |
The 8-bit pairs come from a comment in the Linux driver's reset code. If a vendor sheet says "address 0xBA", it is the same device as 7-bit 0x5D; enter 0x5D in Arduino, ESP-IDF and Linux.
Read the product ID
Registers on the GT911 are 16-bit addresses. The Linux driver reads 6 bytes from 0x8140: the first 4 bytes are the product ID as ASCII text and the last 2 are the firmware version (little-endian). A GT911 reports the string 911. If you get 911, the bus, power and address are all fine and the problem is further down this list.
If nothing answers at either address, check that the reset line isn't being held low. On many modules RST is an input to the GT911 and has to be driven high by the host (or pulled up on the board) before the controller runs.
2. Get the reset and address-select sequence right
The GT911 picks its I2C address from the level on its INT pin at the moment reset is released. In the words of the Linux binding, the INT line "is sampled by the device on reset deassertion to select the I2C client address".
INT level when RST goes high | I2C address |
|---|---|
Low | |
High | |
The sequence the Linux driver uses
- Drive RST low and wait more than 10 ms (the driver waits 20 ms).
- Drive INT to the level for the address you want: high for
0x14, low for0x5D. - Wait more than 100 µs.
- Drive RST high and wait more than 5 ms (the driver waits 6–10 ms).
- Drive INT low for 50 ms, then switch INT to an input.
If INT floats during step 4, the address can differ from one power-up to the next. That is the classic "works after flashing, fails after a cold boot" report.
ESP-IDF: esp_lcd_touch_gt911
Espressif's component defines ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS as 0x5D and ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP as 0x14. It only runs the address-select sequence when all three of these are set:
rst_gpio_numis a real GPIO (notGPIO_NUM_NC),int_gpio_numis a real GPIO,driver_datapoints to anesp_lcd_touch_io_gt911_config_twhosedev_addris the address you want.
Otherwise it logs I2C address initialization procedure skipped - using default GT9xx setup and does a plain reset. In that case the address is whatever the board's wiring gives, and the I2C panel-IO address you pass must match the scan result. The component's default I2C clock in ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG() is 100 kHz.
Boards where the host doesn't control INT
If INT isn't connected to the host, the host can't choose the address, so scan both addresses and use the one that answers. On the Sunton ESP32-8048S043C, for example, the GT911 interrupt isn't wired to a GPIO by default (see our board page). ESPHome's GT911 page notes that when INT goes through an IO expander, the pin is still used to set the address at boot, but touch is polled instead of interrupt-driven.
3. Detected, but no touch events
Read and clear the status register
Touch data starts at 0x814E. The first byte is a status byte:
- Bit 7 (
0x80): buffer ready. New data is valid only when this is set. - Bits 0–3: number of touch points. The Linux driver rejects counts above the configured maximum.
- Bit 4: a key (button) is pressed.
Each touch point that follows is 8 bytes: a track ID, then X, Y and size as little-endian 16-bit values.
After reading, both the Linux driver and esp_lcd_touch_gt911 write 0 to 0x814E. If you write your own driver, do the same; skipping that write is a common reason a hand-written driver sees only the first touch.
Match the interrupt edge
The trigger type is in the GT911's own configuration: bits 0–1 of the config byte at 0x804D (offset 6 from the config start at 0x8047). The Linux driver maps it like this:
Value | Interrupt type |
|---|---|
0 | Rising edge |
1 | Falling edge |
2 | Low level |
3 | High level |
Set your GPIO interrupt to match. In esp_lcd_touch_gt911, levels.interrupt = 1 selects a rising-edge interrupt and 0 a falling edge.
No INT line? Poll
Polling works fine for HMI use. ESPHome polls every 50 ms by default (update_interval) when no interrupt_pin is set. The Linux driver, when it does have an interrupt, waits up to 20 ms for the ready bit before giving up on a frame.
4. Touch lands in the wrong place
Check the resolution stored in the GT911
The GT911 reports coordinates in the resolution written in its configuration, not in your display's resolution. Per the Linux driver, X maximum is the little-endian 16-bit value at 0x8048 and Y maximum at 0x804A. Read them. If the controller is configured for 1024×600 and your panel is 800×480, touches land to the right of and below your finger and the far edges fall off-screen. The fix is to scale (or set the driver's limits to the controller's values).
Where each stack takes the limits from:
Stack | Resolution source | Swap and mirror |
|---|---|---|
Linux | Read from the GT911 config; falls back to 4095 × 4095 when the config has none | Device-tree |
ESP-IDF | Your | |
ESPHome | Touchscreen | |
Calibrate from raw values
ESPHome's touchscreen page suggests logging touch.x_raw and touch.y_raw in an on_touch lambda, touching the corners at the edge pixels a few times, and entering the minimum and maximum raw values as the calibration. The same method works on any platform: print raw X and Y, touch the four corners, and map the range onto the screen.
Fix orientation in this order: first get X and Y on the right axes (swap_xy), then flip whichever axis runs backwards (mirror_x / mirror_y). The display's logical (0, 0) must be top-left.
5. Rewriting the GT911 config: last resort
The configuration block starts at 0x8047. For the GT911 the Linux driver treats it as 186 bytes:
- Byte 0 (
0x8047): config version. - Bytes 1–4: X and Y resolution (see step 4).
- Byte 5 (
0x804C): maximum touch points, low 4 bits. - Byte 6 (
0x804D): interrupt trigger type, low 2 bits. - Byte 184 (
0x80FF): checksum, the 8-bit two's complement of the sum of bytes 0–183. - Byte 185 (
0x8100):config_fresh, which must be1.
The Linux driver itself only writes a config when it has both the INT and RST GPIOs and finds a firmware file (default name goodix_911_cfg.bin, or the name in a goodix,config-name property). Without that file, it uses the config already stored in the chip.
Before you write anything, read all 186 bytes and save them. Fix resolution and orientation in software where you can. A config block made for a different touch panel can stop touch working on yours, so get the file from the panel's supplier if you really need to change it.
Choosing a capacitive-touch module
If you're picking a CTP display for a new design, ask the supplier three things before you order samples: which touch controller it uses, which I2C address it ships at, and whether INT and RST reach the connector. Send your size, interface and host processor through Ask an Engineer, and we'll include those three answers with the modules we suggest.
Frequently asked questions
What is the I2C address of the GT911?
Either 0x5D or 0x14 (7-bit). The controller samples its INT pin when reset is released: INT low selects 0x5D, INT high selects 0x14. Datasheets that list 0xBA/0xBB or 0x28/0x29 are giving the same addresses as 8-bit write/read bytes.
Why does my GT911 change address after a reboot?
INT is floating or driven by something else when reset is released, so the controller samples a different level each time. Drive INT low (for 0x5D) or high (for 0x14) before releasing RST, wait more than 5 ms, hold INT low for 50 ms, then make it an input. If the host can't control INT, scan both addresses.
Why do I only get one touch from the GT911?
After reading the touch data at 0x814E, write 0 to 0x814E. The Linux goodix driver and Espressif's esp_lcd_touch_gt911 both do this after every read; a driver that skips it typically stops seeing new touches.
Why are GT911 touch coordinates scaled or offset?
The GT911 reports in the resolution stored in its own config (X at 0x8048, Y at 0x804A). If that differs from your panel, scale the values or set your driver's x_max/y_max to the controller's resolution, then use swap_xy and mirror_x/mirror_y for orientation.
Does the GT911 work without the INT pin?
Yes. Poll the 0x814E status register instead of using an interrupt. ESPHome polls every 50 ms by default when no interrupt_pin is set. Without INT the host also can't choose the address, so use whichever of 0x5D or 0x14 answers.
Should I rewrite the GT911 configuration?
Only as a last resort. Read and save the existing 186-byte block from 0x8047 first, prefer fixing resolution and orientation in software, and use the touch panel supplier's config file if you must write one. The block ends with an 8-bit checksum at 0x80FF and a config_fresh byte at 0x8100 that must be 1.
Sources
- Linux kernel: drivers/input/touchscreen/goodix.c
- Linux kernel: drivers/input/touchscreen/goodix.h (register addresses)
- Linux kernel: Goodix touchscreen device-tree binding (goodix.yaml)
- Espressif ESP-BSP: esp_lcd_touch_gt911 driver source
- Espressif ESP-BSP: esp_lcd_touch_gt911 header (I2C addresses)
- ESPHome: GT911 touchscreen
- ESPHome: Touchscreen components (transform, calibration)