Interface ILI9341 based TFT display with T4.0

Lavanya rajan

Well-known member
Hello All,

I'm trying to interface a 2.4" TFT SPI 240x320 display with a Teensy 4.0 microcontroller. The pin connections follow the setup described in the link below, except that the CS (Chip Select) pin is connected to pin 9, and the DC (Data/Command) pin is connected to pin 10.

I'm using the following code, but the text on the display appears mirrored, even though the rotation is set correctly and also The background color isn't displaying properly — I'm using fillScreen(RED), but the screen shows blue instead.. Can anyone help me figure out what's causing this and how to fix it?

Code:
#include <SPI.h>
#include <Wire.h>
#include <ILI9341_t3.h>

// Define pins for the TFT display
#define TFT_CS 9
#define TFT_DC  10

ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

void setup(void) {
  Serial.begin(9600);
  tft.begin();

  // Try different values (0 to 3) if needed: 0 = portrait, 1 = landscape, 2 = upside down, 3 = other landscape
 
  tft.setRotation(1); // Usually best for non-mirrored portrait
  tft.fillScreen(ILI9341_RED); // Set background to blue

  // Optional: disable text wrapping
  tft.setTextWrap(false);

  // Set text properties
  tft.setTextColor(ILI9341_WHITE); // Text color
  tft.setTextSize(2);              // Text size
  tft.setCursor(30, 30);           // Adjust position

  // Display the message
  tft.println("Hello World!!!");
}

void loop() {
  // Nothing to do here
}
 

Attachments

  • WhatsApp Image 2025-06-24 at 14.10.01.jpeg
    WhatsApp Image 2025-06-24 at 14.10.01.jpeg
    115.7 KB · Views: 16
  • WhatsApp Image 2025-06-24 at 14.10.02.jpeg
    WhatsApp Image 2025-06-24 at 14.10.02.jpeg
    151.2 KB · Views: 16
what version of teensyduino and what IDE are in use?

Try one of the examples included with the library just to be sure the behavior persists.
 
I'd close the IDE and restart using one of the examples like:

"T...\hardware\teensy\avr\libraries\ILI9341_t3\examples\graphicstest\graphicstest.ino"

There may be a badly compiled file in the TEMP build folder.

Also with Verbose build at the end the actual library in use is noted and it should link to the one in the TeensyFolder and not a local library copy - something like this (as shown using path for IDE 1) - there is will come from the USER APPDATA LOCAL folder (windows?) but the BOLD TAIL shown and version should be similar:

Using library ILI9341_t3 at version 1.0 in folder: T:\T_Drive\arduino-1.8.19\hardware\teensy\avr\libraries\ILI9341_t3
 
So, this is the location where all files are saved C:\Users\SMDDC2\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\ILI9341_t3\examples\graphicstest

I uploaded the graphicstest.ino available in the above path, again everything is displayed in inverted
 
Something odd about the display there it seems. Not the same or using the same actual interface chip.

AFAIK this hasn't shown up in the years this display has been in use.
Is only a single copy of this display there to test?
Compare the visible markings on the PJRC page - and maybe upload a phonto of the backside not showing on that page.
 
Something odd about the display there it seems. Not the same or using the same actual interface chip.

AFAIK this hasn't shown up in the years this display has been in use.
Is only a single copy of this display there to test?
Compare the visible markings on the PJRC page - and maybe upload a phonto of the backside not showing on that page.
I already uploaded backside of the display in the top
 
already uploaded backside of the display in the top
indeed :)
That is 2.4" - the handy ones here are not 2.4" so not clear that may not have a different controller that ILI9341. SImple variations can show big differences.

PJRC suggests 2.8" or 3.2" were the common sizes used when ILI9341 code was tested
 
Any input on how to sort out this issue
indeed :)
That is 2.4" - the handy ones here are not 2.4" so not clear that may not have a different controller that ILI9341. SImple variations can show big differences.

PJRC suggests 2.8" or 3.2" were the common sizes used when ILI9341 code was tested
 
I'm using examples codes from this link https://github.com/vindar/tgx which contains programs related to T4.0, I uploaded few examples and all these are appearing inverted
I had similar inversion with tgx library using ST7789, 240x320, 2.8", parallel 8/16-bit. In one of the tgx files, I had to flip the "invert color" bit to fix the issue. I suspect you'll have to do the same fix. For IL9341, that's found in register 0x21.
 
Any input on how to sort out this issue
First suggestion, edit the file ILI9341_t3.cpp (library is installed by Teensyduino)

Look at the setRotation function:
Code:
void ILI9341_t3::setRotation(uint8_t m)
{
    rotation = m % 4; // can't be higher than 3
    beginSPITransaction(_clock);
    writecommand_cont(ILI9341_MADCTL);
    switch (rotation) {
    case 0:
        writedata8_last(MADCTL_MX | MADCTL_BGR);
        _width  = ILI9341_TFTWIDTH;
        _height = ILI9341_TFTHEIGHT;
        break;
    case 1:
        writedata8_last(MADCTL_MV | MADCTL_BGR);
        _width  = ILI9341_TFTHEIGHT;
        _height = ILI9341_TFTWIDTH;
        break;
    case 2:
        writedata8_last(MADCTL_MY | MADCTL_BGR);
        _width  = ILI9341_TFTWIDTH;
        _height = ILI9341_TFTHEIGHT;
        break;
    case 3:
        writedata8_last(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
        _width  = ILI9341_TFTHEIGHT;
        _height = ILI9341_TFTWIDTH;
        break;
    }
    endSPITransaction();
    cursor_x = 0;
    cursor_y = 0;
}
In this function change the instances of: MADCTL_BGR
to: MADCTL_RGB

save and try rebuilding your sketch and see if that solves it.
 
First suggestion, edit the file ILI9341_t3.cpp (library is installed by Teensyduino)

Look at the setRotation function:
Code:
void ILI9341_t3::setRotation(uint8_t m)
{
    rotation = m % 4; // can't be higher than 3
    beginSPITransaction(_clock);
    writecommand_cont(ILI9341_MADCTL);
    switch (rotation) {
    case 0:
        writedata8_last(MADCTL_MX | MADCTL_BGR);
        _width  = ILI9341_TFTWIDTH;
        _height = ILI9341_TFTHEIGHT;
        break;
    case 1:
        writedata8_last(MADCTL_MV | MADCTL_BGR);
        _width  = ILI9341_TFTHEIGHT;
        _height = ILI9341_TFTWIDTH;
        break;
    case 2:
        writedata8_last(MADCTL_MY | MADCTL_BGR);
        _width  = ILI9341_TFTWIDTH;
        _height = ILI9341_TFTHEIGHT;
        break;
    case 3:
        writedata8_last(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
        _width  = ILI9341_TFTHEIGHT;
        _height = ILI9341_TFTWIDTH;
        break;
    }
    endSPITransaction();
    cursor_x = 0;
    cursor_y = 0;
}
In this function change the instances of: MADCTL_BGR
to: MADCTL_RGB

save and try rebuilding your sketch and see if that solves it.
The issue related to colour inversion "The background color isn't displaying properly — I'm using fillScreen(RED), but the screen shows blue instead." has been sorted now with this solution, but still struggling with text inversion
 
Last edited:
I had similar inversion with tgx library using ST7789, 240x320, 2.8", parallel 8/16-bit. In one of the tgx files, I had to flip the "invert color" bit to fix the issue. I suspect you'll have to do the same fix. For IL9341, that's found in register 0x21.
previously it was 0x21 and now I changed to

#define ILI9341_INVOFF 0x20
#define ILI9341_INVON 0xFF
#define ILI9341_GAMMASET 0x26
#define ILI9341_DISPOFF 0x28
#define ILI9341_DISPON 0x29

but it is not sorted yet
 
So, got this issue sorted out. In case, in future if anyone had this issue, modify the ILI9341_t3.cpp file.

look for setrotation function

Code:
switch (rotation) {
    case 0:
        writedata8_last(MADCTL_MX | MADCTL_RGB);
        _width  = ILI9341_TFTWIDTH;
        _height = ILI9341_TFTHEIGHT;
        break;
    case 1:
        writedata8_last(MADCTL_MV | MADCTL_RGB);
        _width  = ILI9341_TFTHEIGHT;
        _height = ILI9341_TFTWIDTH;
        break;
    case 2:
        writedata8_last(MADCTL_MY | MADCTL_RGB);
        _width  = ILI9341_TFTWIDTH;
        _height = ILI9341_TFTHEIGHT;
        break;
    case 3:
        writedata8_last(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_RGB);
        _width  = ILI9341_TFTHEIGHT;
        _height = ILI9341_TFTWIDTH;
        break;
    }

In this function change the instances of: MADCTL_MX | MADCTL_RGB
to: !MADCTL_MX | MADCTL_RGB
 
I tried your .ino on a Teensy 4.0
Arduino IDE 2.3.2
Teensyduino 1.57
ILI9341_t3 that delivers with Teensyduino
Add default compiler settings (600 mhz/faster)

using an ILI9341 with these 3 sizes: 2.2", 2.4" and 2.8"

All displays show a red background with text properly drawn

Not sure what the issue could be. Sorry,
 
There are variants if the ILI9341 that are basically compatible but require a slightly different initialization sequence.

TFT_eSPI handles these, so I would look there in Bodmer's defines - the init and rotation headers for the ILI9341 variants and you should find the sauce.
 
I tried your .ino on a Teensy 4.0
Arduino IDE 2.3.2
Teensyduino 1.57
ILI9341_t3 that delivers with Teensyduino
Add default compiler settings (600 mhz/faster)

using an ILI9341 with these 3 sizes: 2.2", 2.4" and 2.8"

All displays show a red background with text properly drawn

Not sure what the issue could be. Sorry,
Hello Sir,

I'm trying to use your number-keypad code (https://github.com/KrisKasprzak/Adafruit_ILI9341_Keypad), but during compilation of the code I'm having errors like


Code:
In file included from C:\Users\SMDDC 2\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\Adafruit_ILI9341_Keypad-main\Examples\Numberpad\Numberpad.ino:5:
C:\Users\SMDDC 2\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\Adafruit_ILI9341_Keypad-main/Adafruit_ILI9341_Keypad.h:197:29: error: section attribute not allowed for 'check'
  197 |         const unsigned char check [350] PROGMEM = {
      |                             ^~~~~
C:\Users\SMDDC 2\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\Adafruit_ILI9341_Keypad-main/Adafruit_ILI9341_Keypad.h:222:29: error: section attribute not allowed for 'backspace'
  222 |         const unsigned char backspace [210] PROGMEM = {
      |                             ^~~~~~~~~
C:\Users\SMDDC 2\AppData\Local\Arduino15\packages\teensy\hardware\avr\1.59.0\libraries\Adafruit_ILI9341_Keypad-main/Adafruit_ILI9341_Keypad.h:239:29: error: section attribute not allowed for 'cancel'
  239 |         const unsigned char cancel [350] PROGMEM = {
      |                             ^~~~~~
Multiple libraries were found for "XPT2046_Touchscreen.h"

How to sort this issue, make this code to run on T4.0
 
Last edited:
Library fixed. I've made some internal changes as well to reduce memory consumption and speed things up. The init for the number pad includes and extra parameter. I would recommend deleted current installs of the ILI9341_t3_Keypad and getting the latest at


Examples updated as well and tested with Teensy 3.2 and Teensy 4.0.
 
@KrisKasprzak
Library fixed. I've made some internal changes as well to reduce memory consumption and speed things up. The init for the number pad includes and extra parameter. I would recommend deleted current installs of the ILI9341_t3_Keypad and getting the latest at
Just gave it a try on the micromod and keypad_numpad displays correctly.
 
Back
Top