Interfacing colored LCD ILI9341 with 8-bit Microcontroller

For my current project, a compact sized multiband transceiver, I wanted to have a colored LCD module as display. On the web I found the ILI9341 LCD. This display has got up to >200000 different colors (depending on the respective mode you chose) and a resolution of 320×240 pixels. It can be driven in various parallel and serial (SPI) modes, therefore it is very versatile. Price for the LCD is about 10 US$ (11€).

First I developed code for a 4-line SPI interface. The display worked, but I found that it was much too slow. A lot of data has to be transferred because due to the higher resolution of the LCD I chose a 12×16 pixel font. That is very much for a small microcontroller (I am using an old ATMega128) clocked to 16 MHz via serial transmission

But I loved the colors and the luminance of the LCD. After a brief research I found that there is also a PCB available for parallel driving. This is sold as a “CP11003” display. The ATMega128 has plenty of ports and that made me think of driving it in parallel mode.

This display has 16 data connectors (DB0:DB15) of which 8 can be used for driving it in parallel mode. As common for parallel bus type LCDs these are the higher 8 bits of the data bus, thus DB8:DB15. DB0:DB7 are not used and therefore not connected.

As control lines there are “RS” (Data or command indicator), “WR” (write operation indicator),”RD” (read operation indicator) and “RES” (reset) are used for control.

CS (chip select) can be connected to GND when the LCD is the only device connected to the 8-bit bus.

ILI9341 LCD TFT display - 8bit parallel bus mode
ILI9341 LCD TFT display – 8bit parallel bus mode

Software development was easy using the GNU C compiler vor AVRs. (I still don’t use Arduino libraries! ;-)) The code can be found after this article.

Final hint: The module also has a touchscreen integrated but that is not in use here!

73 de Peter (DK7IH)

Code for ili9341_par_8bit

11 thoughts on “Interfacing colored LCD ILI9341 with 8-bit Microcontroller”

  1. How fast did you try running the SPI interface? Depending on the slave device, and the processor, clock speeds of several MHZ are possible (short wires!). Also, maybe you should consider switching to using an ARM Cortex processor. The Atmel/Microchip SAMD21 (Arm Cortex M0+) can run at 48mhz, the SAMD51 (ARM cortex M4) at 120 mhz. There are also the Teensy series boards with the 3.2, 3.5 and 3.6 versions running at 72, 120, and 180 MHZ respectively with Arm Cortex M4 processors, and the new Teensy 4.0 Arm Cortex M7 at 600 MHZ. The Teensy boards can also be over clocked to some extent with the 4.0 topping out at over 900 MHZ. Cortex M4 and M7 processors can do DSP work, they have specialized instructions added to speed this up. The ARM Cortex based Arduino like boards are no more expensive than their AVR counter parts, and if you want to go bare IC, you can use the Eclipse IDE to develop your C code, and a dirt cheap ($20) Jlink EDU Lite Jtag to program them. It’s also possible to use the Arduino Zero or even a Raspberry Pi running OpenOCD as a programmer.

    1. Hi there, I did not measure the SPI frequency on with a respective routine. All I can say is that the mircor runs on 16MHz and that there is not any delay in the routine so it performs with max. speed defined by the compiler for that function.

      And, sure, you are right it seems to switch to more powerful controlers. For the the next projects I have look to STM controllers but not sure which one I will use then. vy 73 de Peter

  2. Hallo Peter,
    welche C-Umgebung benutzt Du? ATMEL Studio 7.x? Was würdest Du für den Programmiereinstieg empfehlen?
    Viele Grüße
    de Uli (DF7IY)

    1. Hallo Uli, ich benutze den GNU C-Compiler (GNU CC) mit AVR-Erweiterungen unter Linux. Früher, unter Windows, habe ich WINAVR verwendet. Und wenn Du in C einsteigen willst, finde ich immer noch das Standardwerk von Kernighan&Ritchie ideal. Oder Du googlest nach “C programmieren für AVR”. Da kommt eine Menge zeitgemäßes Material. .Vy 73 de Peter (DK7IH)

  3. For “RS” (Data or command indicator), “WR” (write operation indicator),”RD” (read operation indicator) and “RES” (reset) provide please the pin number (port) of your ATMega128 chip. Or show the schematic diagram please. Thank you.

    1. Hi there, the data lines are defined in the code as stated here:

      Port = PORTB

      #define LCDWR 2 //Write operation indicator (actice low)
      #define LCDRD 4 //Read indicator (actice low)
      #define LCDRES 8 //Reset (active low)

      vy 73 de Peter

      1. Thank you!
        I can ask you, how can I change the procedure lcd_putchar() to use characters larger than 16×12 especially this line:

        for (t0 = 0; t0 < FONTWIDTH * 2; t0 += 2)
        for (t1 = 0; t1 < size; t1++)
        u = xchar[c][t0 + 1] + (xchar[c][t0] <= 0; t2–)

        for example for:
        #define FONTWIDTH 21
        #define FONTHEIGHT 24

        I can not move the third 8-bit at this
        u = xchar[c][t0 + 1] + (xchar[c][t0] << 8) + … ;
        u = … + xchar[c][t0 + 1] + (xchar[c][t0] << 8) ;
        Thank you!

        1. Sorry for
          #define FONTWIDTH 24
          #define FONTHEIGHT 21

          for (t0 = 0; t0 < FONTWIDTH * 2; t0 += 2)
          for (t1 = 0; t1 < size; t1++)
          u = xchar[c][t0 + 1] + (xchar[c][t0] <= 0; t2–)

          1. I actually want to change the procedure to put an image from
            const char xchar[][];
            I will be grateful for your help.

  4. I’m trying like that:

    u = xchar[c][t0 + 2] + (xchar[c][t0 + 1] << 8) + (xchar[c][t0] << 16);

    but does not working ((

    1. Hi there,

      using bigger characters might be a problem. I think I’ still have to do some research about that. Sorry for not having an appropriate solution right now. My “To Do” list gets even longer. 😉
      vy 73 de Peter

Leave a Reply

Your email address will not be published. Required fields are marked *