CTP Touchscreen Driver Guide
Source code:
components/BSP/TDO_CTP/drv/esp32/esp32_ctp.c/esp32_ctp.h/tdo_ctp_conf.h
1. Driver Architecture
LVGL read_cb → touchpad_read()
├─ touchpad_is_pressed() → tdo_ctp_get_point()
└─ touchpad_get_xy() → point.x / point.y
↑
tdo_ctp.c (generic CTP framework)
↑
g_ctp_iic_drv (interface table, registered in esp32_ctp.c)
├─ .iic_write ──→ I2C or LCD SPI (depending on TR230S_EN)
├─ .iic_read ──→ same as above
├─ .gpio_control → INT/RST pin control
└─ .mdelay → vTaskDelay2. Chip Selection
c
// ── File: tdo_ctp_conf.h ──
#define TDO_CTP_ONCE TDO_CTP_GT911 // current: GT911
// Can be changed to:
// #define TDO_CTP_ONCE TDO_CTP_TR230S → enable TR230S (shares LCD SPI/QSPI communication)3. Communication Interface (I2C vs LCD SPI)
c
// ── File: esp32_ctp.c ──
tdo_ctp_iic_drv_t g_ctp_iic_drv = {
#if TR230S_EN
// TR230S mode: communicates by reusing the LCD's SPI3_HOST handle
.iic_write = lcd_reg_write, // → qspilcd.c: lcd_ctp_write_cmd()
.iic_read = lcd_reg_read, // → qspilcd.c: lcd_ctp_read_cmd()
#else
// Standard I2C mode: dedicated I2C_NUM_1 bus
.iic_write = iic_reg_write,
.iic_read = iic_reg_read,
#endif
.gpio_control = ctp_gpio_control,
.mdelay = ctp_mdelay,
};Key point:
lcd_ctp_write_cmd()/lcd_ctp_read_cmd()are defined inqspilcd.c; after acquiring the LCD SPI bus viaspi_device_acquire_bus(), they read and write touch registers using the QSPI frame protocol. See the SPI/QSPI Driver Guide for details.
4. Hardware Initialization
c
uint8_t esp32_ctp_init(void)
{
#if TR230S_EN == 0
// ── I2C mode: configure SDA/SCL, initialize I2C_NUM_1 ──
gpio_config(&gpio_tp_int); // INT: GPIO 45
gpio_config(&gpio_tp_rst); // RST: GPIO 48
i2c_config_t ic = {
.mode = I2C_MODE_MASTER,
.sda_io_num = CTP_IIC_SDA, // GPIO 39
.scl_io_num = CTP_IIC_CLK, // GPIO 38
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = CTP_IIC_FREQ, // 400000
};
i2c_param_config(I2C_NUM_1, &ic);
i2c_driver_install(I2C_NUM_1, I2C_MODE_MASTER,
I2C_MASTER_RX_BUF_DISABLE,
I2C_MASTER_TX_BUF_DISABLE, 0);
// TR230S mode: skip I2C initialization, use the LCD SPI directly
#endif
tdo_ctp_init(); // auto-matches the TDO_CTP_ONCE chip
return 0;
}Touch Pins
| Signal | GPIO | Description |
|---|---|---|
| CTP SDA | 39 | I2C data |
| CTP SCL | 38 | I2C clock |
| CTP INT | 45 | Interrupt |
| CTP RST | 48 | Reset |
5. Touch Read Interface
c
// ── Called periodically by LVGL ──
bool touchpad_is_pressed(void)
{
tdo_ctp_point_t point;
tdo_ctp_get_point(&point); // calls the generic CTP driver
return (point.event == TDO_CTP_EVENT_DOWN ||
point.event == TDO_CTP_EVENT_MOVE);
}
void touchpad_get_xy(uint16_t *x, uint16_t *y)
{
*x = point.x;
*y = point.y;
}6. Supported Chip List
| Driver File | Chip | Communication |
|---|---|---|
tdo_gt911.c | GT911 | I2C |
tdo_ft6336.c | FT6336 | I2C |
tdo_cst328.c | CST328 | I2C |
tdo_gt5688.c | GT5688 | I2C |
tdo_ilitek_v3.c | ILITEK V3 | I2C |
tdo_ilitek_v6.c | ILITEK V6 | I2C |
tdo_st7102.c | ST7102 | I2C |
tdo_icnt8952.c | ICNT8952 | I2C |
tdo_cf1124.c | CF1124 | I2C |
tdo_jd9366tc.c | JD9366TC | I2C |
tdo_tr230s.c | TR230S | LCD SPI (shared) |
7. Porting Checklist
- [ ] Set
TDO_CTP_ONCEintdo_ctp_conf.hto the target chip macro - [ ] Modify the
CTP_SDA/SCL/INT/RSTpin macros inesp32_ctp.h - [ ] In TR230S mode, make sure
lcd_ctp_write_cmd/read_cmdinqspilcd.care implemented - [ ] Call
esp32_ctp_init()inlv_port_indev_init()+ registertouchpad_read
8. Troubleshooting
| Symptom | Things to Check |
|---|---|
| No touch response | I2C scan to confirm the address? Pull-up resistors? TDO_CTP_ONCE match? |
| TR230S not communicating | LCD initialized? QSPI frame format correct? spi_device_acquire_bus() contention? |
| Coordinate offset | Screen orientation lcd_display_dir() consistent with the touch mapping? |