Skip to content

Lesson05_I2C_Touch_GT911: ESP32-P4 I2C Touch GT911

1. Course Introduction

This lesson uses ESP-IDF to initialize the GT911 capacitive touchscreen controller through the I2C master driver and reads touch coordinates via polling. After the program is flashed, the development board powers on and resets; the I2C bus (SDA=GPIO45, SCL=GPIO46) and the GT911 (RST=GPIO40, INT=GPIO42) complete initialization. When the learner touches the screen with a finger, the serial monitor prints the touch coordinates Touch at X=..., Y=... in real time, and stops printing when the finger leaves.

This lesson introduces the I2C bus and touch driver for the first time, and serves as the foundation for subsequent lessons on driving the display and LVGL interaction. Through this experiment, learners will complete end-to-end verification of the full chain: I2C bus creation, device registration, GT911 initialization, and coordinate reading.

2. Learning Objectives

  • Be able to open the Lesson05 project in ESP-IDF and set the target chip to esp32p4.
  • Be able to explain the call order and respective roles of i2c_new_master_bus, esp_lcd_new_panel_io_i2c, and esp_lcd_touch_new_i2c_gt911.
  • Be able to explain the fallback mechanism for the GT911 primary and backup I2C addresses.
  • Be able to complete compilation and flashing, and touch the screen to observe whether the serial port prints coordinates.
  • Be able to determine whether the I2C and touch chain is functioning properly based on whether the coordinates change as the finger moves.

3. Prerequisites

  • Hardware: one CrowPanel Advanced 7 / 9 / 10.1-inch ESP32-P4 HMI AI Display development board, and one USB Type-C data cable that supports data transfer.
  • Compatibility note: The hardware and software code for the 7 / 9 / 10.1-inch development boards are fully interchangeable; only the board dimensions differ. Please select the appropriate model based on display size and use case.
  • Software: VS Code, ESP-IDF Extension (ESP-IDF v5.4 or later).
  • Project dependencies: retain the main/main.c, peripheral/bsp_i2c, and peripheral/bsp_display components, as well as the esp_lcd_touch_gt911 managed component.
  • Configuration: target chip esp32p4; I2C port 0, SDA=GPIO45, SCL=GPIO46, 100 kHz; touch resolution 1024×600.

Code download link:

CrowPanel-Advanced-7inch-ESP32-P4-HMI-AI-Display-1024x600-IPS-Touch-Screen/example at master · Elecrow-RD/CrowPanel-Advanced-7inch-ESP32-P4-HMI-AI-Display-1024x600-IPS-Touch-Screen

4. Software Operation Steps

  1. In VS Code, open the ESP-IDF Extension panel, click Open ESP-IDF Project, and select the Lesson05-Touchscreen folder. Open project

  2. First select the code runtime environment ESP-IDF v5.4.2, set the flashing method to UART, and select the serial port that actually corresponds to your development board. Then click Set Espressif Device Target in the ESP-IDF Extension panel and select esp32p4. Once configured, the status bar should display ESP-IDF v5.4.2, UART, the required COM port, and ESP32-P4. Confirm ESP-IDF, flashing method, serial port, and target chip

  3. Click SDK Configuration Editor in the VS Code bottom status bar or the ESP-IDF extension panel, and wait for the configuration page to fully load before modifying parameters. If the page is still loading, do not click Build immediately. Click SDK Configuration Editor

Wait for SDK Configuration Editor to finish loading

  1. Enter flash in the search box and ensure Flash SPI mode: QIO; Flash Sampling Mode: STR Mode; Flash SPI speed: 80 MHz; Flash size: 16 MB. These parameters should match the onboard Flash of the Advance-P4 board. Configure Flash parameters

  2. After verifying the configuration is correct, click Save in the top-right corner; confirm the changes have been saved, then run Build to compile.

  3. Click Full Clean to clear the cache left over from the previous compilation. Performing this after the first build, when switching project configuration, or after modifying SDK parameters prevents stale configuration from affecting the new build result. Execute Full Clean

  4. Click Build to compile the project. The first build will automatically download the esp_lcd_touch_gt911 component, and on success it outputs Project build complete. Compile the project and confirm success

  5. Confirm the development board is connected to the computer via USB, then click Select Port to Use to choose the serial port.

  6. Click Flash to flash the firmware. Upon completion, it displays Hard resetting.... Click Flash to flash firmware

  7. After flashing is complete, click Monitor to open the serial monitor at a baud rate of 115200. You should see the Touch application started successfully log. Press Ctrl + ] to exit the monitor. Flashing complete and open serial monitor

  8. Finally, you can use the one-click operation button in the ESP-IDF status bar to sequentially execute compile, flash, and open serial monitor. Use this only after the project configuration, serial port, and code have all been confirmed correct; if you need to troubleshoot, you should still follow the steps above one by one. One-click compile, flash, and open monitor

5. Hardware Operation Steps

  1. Connect the ESP32-P4 development board to the computer using a USB data cable. Confirm that the touchscreen FFC cable is correctly inserted into the development board's FPC connector. Connect development board and touchscreen
  2. After flashing is complete and the board resets, observe whether the serial port prints I2C initialization and Touch application started successfully. Reset and observe startup log
  3. Touch any position on the screen with a finger, and observe whether the serial port prints Touch at X=..., Y=...; the coordinates should change as the finger moves. Touch the screen
  4. After the finger leaves the screen, observe whether the serial port stops printing coordinates, confirming that touch detection is working properly. Observe touch coordinate log

6. Key Code Explanation

i2c_master_bus_config_t conf = {
    .i2c_port = I2C_MASTER_PORT,
    .sda_io_num = I2C_GPIO_SDA,
    .scl_io_num = I2C_GPIO_SCL,
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .glitch_ignore_cnt = 7,
    .flags.enable_internal_pullup = true,
};
err = i2c_new_master_bus(&conf, &i2c_bus_handle);

This creates the I2C master bus. sda_io_num/scl_io_num specify GPIO45/GPIO46; glitch_ignore_cnt=7 is the glitch filter length, used to filter out spike interference on the bus; enable_internal_pullup enables the internal pull-up. If the SDA/SCL pins are misconfigured or the pull-up is not enabled, I2C communication will fail and touch initialization will report an error. Note: for high-speed operation (400 kHz) or long traces, an external pull-up is recommended.

err = esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp);
if (err != ESP_OK) {
    io_config.dev_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP;
    ...
}

The GT911 has two I2C addresses (primary and backup); the specific address depends on the level of the INT pin at power-up. The code first uses the primary address and automatically falls back to the backup address on failure. If the fallback logic is removed, initialization may fail under certain power-up sequences, manifesting as the serial port printing Touch initialization failed.

err = esp_lcd_touch_read_data(tp);
...
if (esp_lcd_touch_get_coordinates(tp, touch_x, touch_y, touch_strength, &touch_cnt, 1)) {
    set_coor(touch_x[0], touch_y[0], true);
} else {
    set_coor(0xffff, 0xffff, false);
}

esp_lcd_touch_read_data triggers a single register read; esp_lcd_touch_get_coordinates extracts the coordinates from the internal buffer. Returning true indicates a touch point is present, while returning false indicates no touch. When there is no touch, the coordinates are set to 0xffff as an "invalid" marker. If read_data is called without calling get_coordinates, the cached coordinates will not be updated and the serial port will keep printing stale values.

vTaskDelay(pdMS_TO_TICKS(50));

The task polls every 50 ms. Too long an interval (e.g., 500 ms) leads to sluggish touch response; too short an interval (e.g., 5 ms) wastes CPU and I2C bandwidth. 50 ms strikes a balance between responsiveness and resource consumption.

7. Experimental Phenomena

After the program is flashed and the board resets, the serial monitor outputs:

I (xxx) TOUCH_APP: Starting touch application
I (xxx) TOUCH_APP: Touch application started successfully

The task then enters polling. When the finger is not touching the screen, the serial port prints no coordinates; when the finger touches the screen, the serial port prints continuously.

I (xxx) DISPLAY: X=512 Y=300 strenth=128 cnt=1
I (xxx) TOUCH_APP: Touch at X=512, Y=300

The coordinates should change in real time as the finger moves, with the X range being 0–1023 and the Y range being 0–599. Printing stops after the finger leaves. If the serial port never outputs coordinates, priority should be given to checking whether the I2C pins and the GT911 reset/interrupt pins are correct; if the coordinates do not change as the finger moves, check whether x_max/y_max match the panel.