Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Marcussacapuces91/doc-TFT_eSPI/llms.txt

Use this file to discover all available pages before exploring further.

TFT_eSPI has built-in support for the XPT2046 resistive touch screen controller that is integrated on most SPI-connected TFT modules. The touch controller shares the SPI bus with the display and uses a dedicated chip-select pin to arbitrate access. Because the support is compiled directly into the library, you get a complete touch API — raw ADC readings, pressure measurement, calibrated screen coordinates, and a 4-point calibration routine — without pulling in a third-party dependency.

Enabling Touch Support

Touch functionality is activated at compile time by defining TOUCH_CS in your User_Setup.h file (or platformio.ini). Set it to the GPIO pin connected to the touch controller’s chip-select line:
// In User_Setup.h
#define TOUCH_CS 21    // GPIO pin wired to XPT2046 CS/T_CS
The SPI clock frequency used for touch communication defaults to 2.5 MHz. Override it in User_Setup.h if needed:
#define SPI_TOUCH_FREQUENCY  2500000   // Default: 2.5 MHz
Touch functions are not available when using an 8-bit or 16-bit parallel interface, or when the RP2040 PIO interface is active. In those configurations the compiler will emit an error if TOUCH_CS is defined. Use a third-party touch library (e.g. the XPT2046_Touchscreen library) with a separate SPI instance for parallel-interface displays.

Touch API Reference

All touch methods are member functions of TFT_eSPI and are available on your tft object whenever TOUCH_CS is defined.
getTouchRaw
uint8_t
Read raw ADC values directly from the XPT2046. Populates x and y with the raw ADC counts from the touch controller without applying any calibration mapping.
uint8_t getTouchRaw(uint16_t *x, uint16_t *y);
getTouchRawZ
uint16_t
Read the raw pressure (Z) measurement from the touch controller. Returns a value roughly proportional to touch pressure. Returns 0 when not touched.
uint16_t getTouchRawZ(void);
getTouch
uint8_t
Read calibrated screen coordinates. Validates the touch reading and maps the raw ADC values through the stored calibration matrix to return pixel coordinates. Returns true (1) when a valid touch is detected above threshold. If the touch coordinates fall off-screen, x and y are not updated.
uint8_t getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600);
calibrateTouch
void
Run an interactive 4-point calibration routine. Draws crosshairs on screen at the four corners and prompts the user to touch each one. Stores the resulting calibration matrix in the array pointed to by data (must be uint16_t[5]). color_fg and color_bg set the foreground and background colours for the calibration UI. size controls the size of the calibration markers.
void calibrateTouch(uint16_t *data, uint32_t color_fg,
                    uint32_t color_bg, uint8_t size);
setTouch
void
Restore previously saved calibration data. Pass the same uint16_t[5] array that was populated by calibrateTouch().
void setTouch(uint16_t *data);

Basic Touch Reading Example

#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI();

void setup() {
  Serial.begin(115200);
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  tft.drawString("Touch the screen", 10, 10, 2);
}

void loop() {
  uint16_t x, y;

  if (tft.getTouch(&x, &y)) {
    // A valid touch was detected — x and y are calibrated screen coordinates
    tft.fillCircle(x, y, 4, TFT_RED);
    Serial.printf("Touch at (%u, %u)\n", x, y);
  }
}

Calibration and Saving to Non-Volatile Storage

Raw ADC readings do not map linearly to screen pixels and vary between hardware revisions. Running a calibration once and storing the result means the mapping is accurate on every subsequent boot.
1

Run the calibration routine

Call calibrateTouch() to display the interactive calibration UI. The user touches four corners of the screen; the function writes five uint16_t values into your array.
uint16_t calData[5];

tft.fillScreen(TFT_BLACK);
tft.calibrateTouch(calData, TFT_WHITE, TFT_BLACK, 15);
2

Persist the calibration data

Save the five values to NVS / EEPROM so calibration survives a power cycle. On ESP32 use the Preferences library:
#include <Preferences.h>
Preferences prefs;

prefs.begin("touch", false);
prefs.putBytes("cal", calData, sizeof(calData));
prefs.end();
3

Restore calibration on boot

On subsequent boots, load the saved values and hand them to setTouch():
Preferences prefs;

prefs.begin("touch", true);
if (prefs.getBytesLength("cal") == sizeof(calData)) {
  prefs.getBytes("cal", calData, sizeof(calData));
  tft.setTouch(calData);   // Apply stored calibration
} else {
  // No calibration data found — run calibrateTouch() again
}
prefs.end();

Reading Raw Pressure

getTouchRawZ() returns the raw Z (pressure) value from the XPT2046. It is useful for detecting touch pressure independently of position, or for implementing your own debounce logic before calling getTouchRaw():
uint16_t pressure = tft.getTouchRawZ();

if (pressure > 350) {
  uint16_t rawX, rawY;
  tft.getTouchRaw(&rawX, &rawY);
  Serial.printf("Raw: x=%u  y=%u  z=%u\n", rawX, rawY, pressure);
}
The default pressure threshold used by getTouch() is 600. Lower values make detection more sensitive; higher values require a firmer press. Adjust the threshold argument to suit your panel’s characteristics.

Alternative Libraries for Parallel Interfaces

When driving a display over an 8-bit or 16-bit parallel bus — or via the RP2040 PIO interface — the XPT2046 touch support in TFT_eSPI is disabled at compile time. In those cases, wire the touch controller to a separate SPI bus and use an independent library such as XPT2046_Touchscreen by Paul Stoffregen, which communicates over its own SPIClass instance and does not conflict with the display bus.

Build docs developers (and LLMs) love