View on GitHub


Arduino Due library for interfacing with ILI9341 SPI TFTs

Download this project as a .zip file Download this project as a tar.gz file


A library for interfacing with ILI9341-based TFT's in SPI, Extended SPI and DMA SPI mode optimized for Arduino Due.

ILI9341 with Arduino Due

The library can also be used with Arduino AVR boards like Uno, Mega, Pro Mini, Nano, etc. It is faster than the original Adafruit one but do not expect DMA-like speed increase. It is comparable to some other tweaked Adafruit libraries out there and in addition you get things like custom fonts, arcs, images or ability to take screenshots. Btw. Not all library examples will work because of smaller ROM/RAM space available on AVRs.

ILI9341 with Arduino Pro Mini

This library is based on 3 libraries:

ili9341_t3 from Paul Stoffregen -
SdFat from Bill Greiman -
GLCD from Michael Margolis and Bill Perry -

ili9341_t3 library where various optimizations for Adafruit's ili9341 and GFX libraries were implemented was used as a base for ili9341_due.
One class from SdFat library is used for utilizing Due's DMA in SPI transfers which provides the main speed boost.
gText class from GLCD library was used as a base for rendering custom fonts.

As for the wiring, use Due's and AVR's HW SPI pins (e.g. described here). The pin for CS on Due depends on the SPI mode you choose (see SPI Mode section below for details).


Some of the default settings can be set in ILI9341_due_config.h file.

SPI Mode

// comment out the SPI mode you want to use
//#define ILI9341_SPI_MODE_NORMAL
//#define ILI9341_SPI_MODE_EXTENDED // make sure you use pin 4, 10 or 52 for CS
#define ILI9341_SPI_MODE_DMA

Uncomment the line depending on the SPI mode you want to use. DMA mode is the default. For AVR, it does not matter which mode you use, ILI9341_SPI_MODE_NORMAL is always going to be used since there is no Extended SPI or DMA available on AVRs.

SPI_MODE_NORMAL is the standard SPI mode where you can use any digital pin for CS. In this mode the library will drive the CS pin 'manually'.
SPI_MODE_EXTENDED is the extended SPI mode available in Due the CS pin is handled by the chip (which is faster than handling it in code 'manually'). You are restricted to these 3 pins for CS - 4, 10 and 52 (as described here).
SPI_MODE_DMA is utilizing D(irect) M(emory) A(ddress) to do SPI transfers. You can use use any digital pin for CS.

Here is a video where you can see the speed difference between the modes (v0.x version):

SPI clock divider

For Due:
#define ILI9341_SPI_CLKDIVIDER 2	// for Due

This is used to set the SPI clock frequency on Due, which for example when set to 10 will set the SPI clock frequency to 84MHz/10=8.4MHz. The minimum divider is 1 (84MHz) and maximum is 255 (329kHz). If you are getting glitches on the screen or it just does not work try to use a higher divider to bring the frequency down (e.g. 11 to run it at 8-ish MHz). I was using 20cm dupont cables to connect TFT with Due and haven't had any issues running it with the divider set to 2.

For AVR:
#define ILI9341_SPI_CLKDIVIDER SPI_CLOCK_DIV2	// for Uno, Mega,...

This is used to set the SPI clock frequency on AVR based boards (Uno, Mega,...). You can use one of these values:

You can change the clock divider at runtime by calling the setSPIClockDivider function.



If you do not need scaled fonts (setTextScale function) then you can comment out the define to disable support for text scaling. Text will render a bit faster. Text scaling is enabled by default.

Scaled font:


Set the default spacing between letters in pixels.

Different letter spacings:


Set the default spacing between lines in pixels.

Different line spacings:


If uncommented, the space between lines (defined by DEFAULT_LINE_SPACING) is filled with text background color. By default it is commented out/disabled.

If uncommented/enabled:


#define ARC_ANGLE_MAX 360

This number represents the maximum equal to 360 degrees (full circle). The default is 360 so if you pass in start=25 and end=75 you'll get an arc going from 25 degrees to 75 degrees. If you set ARC_ANGLE_MAX 100 and you pass in start=0 and end=50 then you get a half circle (that can represent percentages). If you set ARC_ANGLE_MAX 2*PI, you can pass in angles in radians etc...You can change the default at runtime by calling the setArcParams function.

#define ARC_ANGLE_OFFSET -90

This number is an offset in degrees from the default position where the arc starts (representing value of 0). If you imagine a compass, then the default starting position is at the East point. Setting the value to -90 will move the starting point 90 degress counter-clockwise (so to the North point).

You can change the offset at runtime by calling the setAngleOffset function. The value provided in setAngleOffset argument is *in addition* to ARC_ANGLE_OFFSET value. So the total angle offset from the default East point is ARC_ANGLE_OFFSET+setAngleOffset value.

Creating Custom Fonts

You can create your own font files by using GLCDFontCreator2 tool. It generates .h files that can then be included in your sketch and the font can be set by the setFont function. The maximum height of a font can be 255 px. GLCDFontCreator2 tool requires Java and it is included in the tools folder or you can dowload it from here.
Here is a quick guide:

  1. Open GLCD Font Creator 2.
  2. From the menu select File->New Font.
  3. Select the Font, Size and Style you want to import in the Import Font group.
  4. Set the Start Index, that's the index from the character map. The first character (space) starts at index 32. The numbers start at index 48, upper-case characters at index 65, etc.
  5. Set the Char Count, that's the number of characters starting at the Start Index you want to have in your character set. So e.g. if you just need the numbers, set the Start Index to 48 and Char Count to 10. That will give you numbers 0-9 in your set.
  6. Set the Font Name. I advice to use maximum of 8 characters, no spaces.
  7. Click OK.
  8. From the menu select Export->Export Font.
  9. Provide a file name. No spaces and the same name as in step 6. Also add ".h" to your file name so you do not have to add it afterwards.
  10. When you click Save, the app starts to export but there is no visible progress. If you do not see the file immediately, just wait for it.
  11. Copy the .h file where your sketch is (or wherever you can find it).
  12. Add an include in your sketch, #include "name_from_step_9.h".
  13. Call tft.setFont(name_from_step_6) and tft.print to render the text.

Custom fonts on AVR (important!)

In order to use generated fonts on Uno, Mega,... you need to manually modify the generated .c file to make it succesfully compile. After you generate a .c file the array definition will look something like this:

static uint8_t Arial_14[] PROGMEM = {

If you do not change anything the compiler will complain with:

error: variable 'Arial_14' must be const in order to be put into read-only section by means of '__attribute__((progmem))'

In order to fix it you need to add "const" so it will look like this:
static const uint8_t Arial_14[] PROGMEM = {

Here is a video of rendering a 255px-high font:


Loading images from an SD card

This is the SdFatTftBitmap example sketch demonstrating loading images from an SD card. The images were converted to RGB565 format using BMP24toILI565 tool (see the Tools folder). One image loads and displays in around 160ms using half speed for SD card SPI and half speed for Due SPI. I was getting distorted images when I tried to use the full speed for either of the SPIs.

This is the Arcs demo from the examples folder:

UTFT demo speed comparison

All the credits (and blame :) goes to TFTLCDCyg who ported the UTFT demo to ILI9341_due library. Both demos were run on Due at the max speed.

Here is a video of the demo powered by the UTFT library:

And here is the demo powered by the ILI9341_due library:

The source code for the ILI9341_due-fied demo can be found in the library's examples folder. Done with ILI9431_due v0.x version. The demo completes in around 1080ms with ILI9341_due v1.x version.

ILI9341_due_Buttons add-on library

Created by Graham Lawrence (aka ghlawrence2000). It's an add-on library which allows to easily add buttons to the UI. See his GitHub page for more information.

Here are videos of two of his example sketches:

ILI9341 functions

Functions summary (in alphabetical order)

Functions details


If you want to ask me a question or just contact me, feel free to do so in the Arduino Forum.

This is a library for the Adafruit ILI9341 display products
This library works with the Adafruit 2.8" Touch Shield V2 (SPI)
Check out the links above for our tutorials and wiring diagrams.
These displays use SPI to communicate, 4 or 5 pins are required
to interface (RST is optional).
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
MIT license, all text above must be included in any redistribution