The TouchTestIRQ example demonstrates a two-stage touch-detection pattern that is strictly more efficient than callingDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/PaulStoffregen/XPT2046_Touchscreen/llms.txt
Use this file to discover all available pages before exploring further.
touched() directly on every loop() iteration. The first stage calls ts.tirqTouched(), which reads a boolean flag that the interrupt service routine (ISR) sets whenever the T_IRQ pin falls — no SPI transaction required. Only when that flag is true does the sketch proceed to the second stage: ts.touched(), which performs the actual SPI read and pressure check. The result is that the SPI bus is left completely idle whenever nothing is touching the screen.
Hardware Required
The T_IRQ interrupt pin must be physically connected for this example to work as described. Connect the T_IRQ (or TIRQ) pad on your TFT module to pin 2 on your Arduino-compatible board.Default Pin Assignments
| Signal | Arduino Pin |
|---|---|
| CS (T_CS) | 8 |
| MOSI | 11 |
| MISO | 12 |
| SCK | 13 |
| TIRQ (required) | 2 |
Full Source Code
Code Walkthrough
Constructor — Interrupt Pin Required
Unlike the plain TouchTest example, this sketch does not offer a commented-out no-IRQ constructor. The TIRQ pin is mandatory:Passing
TIRQ_PIN to the constructor causes begin() to call attachInterrupt() on that pin. The ISR simply sets the isrWake volatile boolean to true on each falling edge, which happens the moment a finger contacts the screen.Stage 1 — ts.tirqTouched()
tirqTouched() reads the isrWake flag and returns its value. This is a plain memory read with no SPI transaction:isrWake is volatile, the compiler will not cache it in a register; every call reads the current value written by the ISR. The flag is cleared internally when touched() or getPoint() performs a real read.Stage 2 — ts.touched()
Once If the T_IRQ signal was a transient glitch and no real pressure is detected,
tirqTouched() confirms that the interrupt fired, touched() performs the SPI read and returns true only if the measured pressure value is ≥ 300:touched() returns false and getPoint() is never called — the SPI bus is released immediately.Performance Advantage
In aloop() that also drives an SD card, a display, a radio module, or any other time-sensitive task, the cost of a single SPI transaction to the XPT2046 is non-trivial — typically several microseconds of bus occupancy plus the overhead of SPI.beginTransaction() / SPI.endTransaction(). Multiplied across hundreds of loop() calls per second when nothing is being touched, this adds up.
The two-stage pattern collapses that cost to a single boolean load on the vast majority of iterations:
| Condition | tirqTouched() cost | touched() cost |
|---|---|---|
| Screen idle | ~1 ns (flag read) | ~50–200 µs (SPI) |
| Screen touched | ~1 ns (flag read) | ~50–200 µs (SPI) |
ts.touched() call is skipped entirely, leaving the SPI bus free for other peripherals without any added latency.
The
delay(30) inside the touched block prevents the Serial Monitor from being flooded during a sustained press. It does not block tirqTouched() from firing on the next loop() iteration — if the user is still touching when the delay expires, isrWake will already be true again and the read will proceed immediately.