Library 08- ILI9341 LCD for STM32F4

One the left is LCD on STM32F429 Discovery board and on the right is LCD shield from eBay.On STM32F429 Discovery board there is LCD with ILI9341 controller. It has 240 x 320 pixels resolution and 16bit or 18bit color depth, what gives you 65536 or 262144 different colors.

It has also a possibility of different way of connection, like serial, parallel, with VSYNC and HYSNC.

STM32F429 has also LTDC driver for LCD like that, but this driver we will use later. For now we will use SPI for driving in serial mode and some other pins for controlling.

I choose this way because on ebay there is a lot of this displays configuring for SPI driving.

If you want to use ILI9341 with LTDC on STM32F429-Discovery board, then check this library.

June 06, 2015

After some optimization videos from Jean-François Garcia and electrodacus I thought that adding that optimizations to my library is not bad idea.

So now, DMA is used for SPI and window/page settings is used before sending data to LCD for reducing time for LCD.

Currently, I’ve set these options:

  • SPI is changed from 8-bits to 16-bits before sending starts via DMA for correct colors,
  • page/window is supported for filling entire LCD, filling rectangle at desired position, drawing vertical or horizontal line
  •  Adding this feature also to fonts which first draws rectangle is not supported yet

So, for maximal support for this LCD, redownload all libraries because I’ve done some changes in TM SPI, TM DMA, TM SPI DMA and TM ILI9341 libraries.

Library

Features

  • Support for 7 x 10 and 11 x 18 pixel font sizes
  • Display string
  • Draw rectangles, circles, lines
  • LCD rotation in all 4 orientations
  • Support for \n and \n\r
    • \n put string into new line with x coordinate same as start x coordinate
    • \n\r put string into new line with x = 0 coordinate
  • Support for LCD display ON/OFF

Dependencies

  • CMSIS
    • STM32F4xx
    • STM32F4xx RCC
    • STM32F4xx GPIO
    • STM32F4xx SPI
    • STM32F4xx DMA
  • TM
    • TM SPI
    • TM DMA
    • TM SPI DMA
    • TM Fonts
    • TM GPIO
    • defines.h

On board, LCD is connected to:

LCD BOARD DISCOVERY BOARD DESCRIPTION NOTES
SDO (MISO) PF8 Output from LCD for SPI Not used, can be left
LED 3.3V Backlight
SCK PF7 SPI clock
SDI (MOSI) PF9 SPI master output
D/C PD13 Data/Command register
RESET PD12 Reset LCD Not used on discovery board
CS PC2 Chip select for SPI
GND GND Ground
VCC 3.3V Positive power supply

Remember: This library can also be used, if you are not using STM32F429 Discovery. It can be used in previous STM32F4 Discovery board. All pins can be changed in defines.h file which is included in project.

By default, SPI5 is used, but you can change that also in defines.h file with

About library

When you included all files to you project, you have to initialize LCD first. Then you are able to work with.

Example describe everything what you need to start with,

Example

Project is available on Github, download library below.

Icon
TM STM32F4 ILI9341 Library

ILI9341 LCD controller driver without LTDC support

tilz0R

Owner of this site. Also electronic enthusiasts, web developer, 3D printer fan, handball player and more. Big fan of STM32F4 devices. In anticipation of the new Discovery board for STM32F7 lines.

You may also like...

Read before commenting!

Before you make a new comment, make sure you agree with things listed below:

  • - Read post to make sure if it is already posted what you are asking for,
  • - Make sure you have the latest version of libraries used in your project,
  • - Make a clean and grammatically correct written message,
  • - Report as many details as possible, including what have you done so far,
  • - Do NOT post any code here. Use Pastebin,
  • - Do NOT post any error codes here. Use Pastebin,
  • - Specify STM32Fxxx family and used Discovery/EVAL/Nucleo or custom made board,
  • - Make sure your clock is set correct for PLL,
  • - If you are using my HAL drivers, please check this post how to start.
Comment will be deleted on breaking these rules without notification!
  • Fadster

    God Bless you Majerle! This is what i have been looking for.. Thanks for sharing and i look forward to learning from you.

  • kim myoung soo

    dear mr. Tilen Majerle
    i’m sorry, but i need hardware and software source, “Library 08- ILI9341 LCD on STM32F429 Discovery board”
    Can you provide me this
    Thank you

    • Buy LCD on ebay, software is on my Github acc.

  • Hi, I read your codes and found that in the “TM_ILI9341_Init()” function, TM_ILI9341_Fill(ILI9341_COLOR_WHITE) is called before initialize the ILI9341_Opts.width and ILI9341_Opts.height.

    Is it correct?

    Thanks

    • ILI9341_Opts.width and ILI9341_Opts.height are only set for internal uses, because LCD can be set to landscape mode and than are width and height different.

      That’s basic idea of this 2 options. LCD is by default in portrait mode and you just have to fill X * Y pixels with desired color, in my case is white.

      • Hi,

        I mean ILI9341_Opts.height and ILI9341_Opts.width are used in the TM_ILI9341_Fill(ILI9341_COLOR_WHITE) function before initialize them.

        You can check in the TM_ILI9341_Init() function. Personally think it is a bug.

        • Yes Yes, it looks like a bug. I have fixed it now. Download link is updated.

          Thanks 😉

          • You are welcome, good luck to your ebay shop.

  • Gabbleduck

    Tried the standard c and h files on the ebay site, no luck, but got it working with your code in about 15minutes after a bit of hacking about, thanks a bajillion!

  • elsol

    Great work! Thanks a million for sharing.
    How can I make more compatible fonts?

    • Well, I found them on internet.
      There are probably some kind of font converters online.

  • fred

    I have trouble with your library in EM Block… out of the box the project won’t compile because spi4 5 and 6 are not existing? I selected stm32f429 in emblock.. any tips? Also, your define,h file is empty is it normal? Thanks

    • It looks like drivers for f429 in em blocks are not written with all options. Download std perip drivers fron st and replace with new one.

      Defines empty, this is ok.

      • fred

        Thanks for the quick response I will try that and keep you posted!

  • Ahmad

    thanks for your great work, do you have any suggestion for using it with KEIL emwin ?

  • Richie

    It works great.
    You may need to update the following files:

    cmsis_boot/stm32f4xx.h
    cmsis_lib/include/stm32f4xx_gpio.h
    cmsis_lib/include/stm32f4xx_rcc.h
    cmsis_lib/source/stm32f4xx_gpio.c
    cmsis_lib/source/stm32f4xx_rcc.c

    I downloaded and replaced stm32f4 dsp stdperiph lib from st to make the project work in CooCox with stm32f429i-disco. Thanks for sharing this library.

  • Jo Van Montfort

    Where you get the color table(map)?

    • I made a color “table” for some colors, it’s not so hard. You have 16bits color code.

      RRRRRGGG GGGBBBBB
      5 bits of red, 6 bits of green, 5 bits of blue.
      Now you can do colors you want.

      My color table is stored in .h file of this library, defines start with ILI9341_COLOR_xxx

  • Jo Van Montfort

    How you print more strings to the screen without refreshing it?

    • Dont understand you what you want now.

      • Jo Van Montfort

        If I use _Puts function the screen gets refreshed. I mean cleared the old string and then the new characters are put.

        • Correct, string is written to lcd board.

          • Jo Van Montfort

            I want to retarget printf to the screen. Not for Debugging purposes!

          • It’s simple.
            In your fputc function add 2 static uint16_t x and y variables.
            After each call of this function, check for character and do your stuff.

            You can use Putc to put single character to LCD.

          • Jo Van Montfort

            How does _Putc function know the position of the next character? Does it remember the last position?

          • It does not. You have to manually set coordinates.

  • Jo Van Montfort

    @majerletilen:disqus Your driver is doing a great job here at my board! Does it provide a function to read the RAM data from the LCD-controller?

    • No, it does not support that feature.
      Maybe I can add this too.

      • Jo Van Montfort

        That would be a great feature! I red it is useful for XOR draw.

  • Patrick Weggler

    Hi,

    thanks for the great lib. It took me only one hour to make it compatible to the stm32f100.

  • Petr Machala

    Hi,

    may I ask if it would be possible to make this SPI commucation to the LCD as non-blocking. I mean if it would be possible to use DMA to simply transfer data over SPI outside the MCU.

    I use DMA with DCMI bus and I think it might be possible to use DMA as a direct connection from (&DCMI->DR) to (&SPI5->DR). But I’m not sure how it would work. Can I send for example full 16b RGB565 or only as a 8b? Can I send it as a continous stream or I have to use a WRX_SET, CS_RESET and CS_SET commands with every “halfpixel” (8b)?

    I think that the control signals are the problem part because than the format of the data can be easily changed by the DMA channel.

    • You cant use directly from one to another peripheral. You have to save to memory first. If you set spi5 tx dma request and set CS to low, then you can continously send data via dma.

      And you have external buffer on f429 so from dcmi to external buffer na from there via spi to lcd.

      • Petr Machala

        Oh sorry for that, you’re a genius. I forgot that DMA connot channel pro peripherial to peripherial. The continous is transfer is great but what data format? 16b or 8b? You’re using uint8_t. Is it mandatory? And by external buffer you mean a SDRAM?

        • for SPI you set peripheral data bus to 8bit. One pixel has 2 bytes so 2x8bit will be send for one pixel.

          No problem here.
          Yes, for external buffer I meant SDRAM. You have it there already and library to use it, no problem at all 🙂

          • Petr Machala

            yeah no problem, but I still cannot find a solution 🙂 SPI_DMA initialized, in IRQ from DCMI_DMA I set commands below and I still get a blank white page…

            LCD_ILI9341_SetCursorPosition(0, 0, ILI9341_Options.width – 1, ILI9341_Options.height – 1);
            LCD_ILI9341_SendCommand(ILI9341_GRAM);
            ILI9341_CS_RESET;
            SPI_I2S_DMACmd(SPI5, SPI_I2S_DMAReq_Tx, ENABLE);

          • Did you enable global DMA settings?
            Try first enable SPI TX DMA and after that enable dma stream.

  • Petr Machala

    Hi,

    I dont want to bother but I am still working on managing a SPI connection with the LCD through a DMA and I need a helping hand. After 2 days I discovered that DMA controller doesnt work as smoothly as I expected…From my experience it is impossible to use DCMI and SPI5 because it is on a same controller DMA2 and there is a crash in memory. I found that it might be possible to make it work if I use something from DMA1, for example a SPI2 connection. Is there some way to send data do the LCD from SPI2 like same kond of loop? Thank you very much…

    • You can use only spi5 because physical connections are on pinc for this spi. You can use external ili9341 spi lcd and do like you said.

      • Petr Machala

        yeah I thought so but I was still hoping for some magical bridge function of the MCU…anyway thanks for your help…

      • Guest

        Sadly that wasnt a problem…I am desperate now…DCMI over DMA to RAM memory works fine but than the RAM memory over DMA to SPI communication is still corrupted…
        I am only getting a 1/4 of the display and all the colors are corrupted too…in a quit a wierd way…for exmaple a 0x001F becomes 0x07E0 and backwards 0x07E0 becomes 0xF800…
        It looks like a DMA doesnt care about some busy time on the SPI and just puts the data whenever it fancy it…

  • fred

    How did you create your fonts? i nedd bigger fonts…
    Thanks

  • Johnny 5

    Hi,
    Thanks for creating these pages! Can you tell me how to adapt this project for the STM32F411 Nucleo board?
    Thank you!!

    • Without problem.
      Just select custom spi settings.

      How to do that is explained above.

      • Alex Sam

        Hi,

        I’m sorry for stupid question, but I can’t connect this monitor to my STM32F401RE. I’ve updated defines.h file by adding lines:
        #define ILI9341_SPI SPI1
        #define ILI9341_SPI_PINS TM_SPI_PinsPack_1
        And connect LCD to board like this:
        LCD->Board
        SCK->PA_5(D13)
        MISO->PA_6(D12)
        MOSI->PA_7(D11)
        CS->???
        D/C->???
        RESET->???

        I’m very new in STM. Please help.
        Thanks!

        • Look pinout above!

          • Alex Sam

            I’ve connected all pins, reconfigured it in defines.h but LCD still don’t working. May this line:
            GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;

            be a root of problem with my 84MHz core?
            How I can redefine it?

          • Board was successfully tested on f401 by some user here on comments.
            Please check your pinout again.

          • Alex Sam

            Yes, it was my fail. It works, but wery slow. Is it any chance to speed it up? I need output only text but for now it draw pixel by pixel.

          • To draw text, you have text functions for string and character.
            Set SPI prescaler to lower value.

            defines.h:
            #define TM_SPIx_PRESCALER SPI_BaudRatePrescaler_2

            Change x for number with your SPI you use for ILI9341 LCD

          • Alex Sam

            Added
            #define TM_SPI1_PRESCALER SPI_BaudRatePrescaler_2
            But this not help

          • Is your clock for Nucleo F401 set OK?

            Well, then this is faster as possible.

            Actually, on F401 at 84MHz, SPI1 can work with max frequency of 42MHz, which is quite fast.

            Make sure you did it right.

  • Petr Machala

    Hi,
    I finally made kind of a progress with the SPI and DMA transfer, but I have to always rearrange the data of the detected image from DCMI before transfer over SPI. Is it possible to switch the order of the bytes in transfer. It’s kind of a bummer having to send first HIGH byte and then LOW byte…Thanks…

    • Petr Machala

      Somewhere in the init function surely but I cant get any information about the init instance…

    • Petr Machala

      Does anyone has a functioning example where LSB and MSB is swaped? My final fconfiguration is adding this but it doesnt work…

      LCD_ILI9341_SendCommand(ILI9341_INTERFACE);

      LCD_ILI9341_SendData(0x01);
      LCD_ILI9341_SendData(0x30);
      LCD_ILI9341_SendData(0x20);
      LCD_ILI9341_SendCommand(ILI9341_RGB_INTERFACE);
      LCD_ILI9341_SendData(0x40);

  • GunterO

    Hello,

    I made some port for the µGFX library which relies on your libraries.

    Maybe it is helpful for somebody. You can find more info here:

    http://forum.ugfx.org/viewtopic.php?f=23&t=182&p=1405#p1405

  • Petr Machala

    Hi,

    Is it possible to turn off the backlight of the 32F429IDISCOVERY LCD? I did not realized it until I started dealing with power consumption… I switch MCU to standby mode which is great but LCD is still shining unnecessarily…

    • http://screencloud.net/v/m4HM

      Directly to 3V3 connected.

      • Petr Machala

        Are there any possibilities?

        • first is to read ILI9341 datasheet if there is command to turn off LED-s by software but I don’t think it is possible here,
          second is to use knife and remove pcb trace line from 3V3 to led pin.

          • Petr Machala

            ILI9341 supports brightness functions but it doesnt work…it’s on 0x51 address…at least it doesnt work on my disco kit…

          • Ii will test when I get disco in hands.

    • Petr Machala

      Just for others…I haven’t found any solution so far…I find it strange that ILI9341 can’t cut the power but I had no choice but to modify the LCD wiring…It’s risky but it worked for me…just remove the power supply for LEDs (#44 behind the display) and then solder a wire to one of the LEDs anode…then through a transistor you’re able to connect and disconnect power supply to LEDs as pleased…

      • Like I said before 😉

        • Petr Machala

          but you have to admit that this is not elegant at all…

          • I just said, that it’s probably not possible, because leds have separated VCC pin.

    • That’s why datasheet is for. But no, you can not do it with software. Only with hardware remove pin.
      Why would you care for one development board how much current LCD uses?

      • Petr Machala

        Interesting that you reply to year old comment…
        When I was dealing with this problem I wanted to decrease the power consumption as much as possible because I was designing a battery powered device that would fit into your hand and would be same size as the board. And a was in quite of a rush…
        Sadly I discovered that the LCD is lid all the time so even when the MCU is in sleep the board consumes a lot power and the battery is alive for only few hours. Anyway for others, The LCD backlight can be disabled only on HW layer by cutting the power to it (by cutting the wire on anode side or removing R47…R50 on cathode side).
        Now its not that relevant to me because even though you turn of the LCD backlight and put MCU to sleep there is still the ST-LINK programmer and that consumes also quite a lot of power.
        My only solution would be to have an external RTC and the all the power…
        Anyway thank you very much for your reply…

  • Mihai Ignat

    Hello. Is there any way of refreshing the screen without using TM_ILI9341_Fill function? I want to plot some points calculated for data from a senzor on the screen. Thank you.

    • You have to physicaly change pixel colors so you can first fill entire LCD and then do stuff again and again.
      SPI LCD is not good choice for that btw 🙂

      • Mihai Ignat

        Can’t I give the command ILI9341_RESET or something like that so that the LCD resets all the pixels at the same time?

        • Then you have to init everything again.

          • Mihai Ignat

            I think I will try to plot just the points and then plot the same points on the same positions with white colour. I wanted to plot the points connected by lines, but the screen is too small so it won’t matter.

  • QIanyu Yin

    Hi,
    Thank you for this library.
    I am developing a drawing board using your display functions. In the while loop in the main(), I have successfully get the X and Y coordinates, But I cannot use DrawPixel() function, nothing is shown on the screen. Out side while loop, If I use DrawPixel, DrawLine, DrawCircle functions, I can display what I want to draw. Can you help me out?

    Thank you very much.

    • Maybe you are not using this method correct, or you did not set correct value.

      Use pastebin to show me your example with DrawPixel function.

  • electrodacus

    Hi,
    Thanks for the library. I made modification to the library since it was way to slow and now is in some cases up to 10x or more faster.
    I just started working on it but maybe you are interested in implementing the changes.
    I posted yesterday two videos on my youtube channel check the video description for details https://www.youtube.com/watch?v=WapdjBnF7tQ

    • Nice from you to make some ads to yourself 😉
      Well, you can also write where you got lib 😉

      Nice work btw

      • electrodacus

        I will give you my rough version soon just started working on the LCD about 3 days ago. The code will not look nice since I’m not an organised person in general 🙂 and I’m much more a HW engineer than a software.
        I was just not happy with the speed for the type of menu I want to implement and I was looking at the ili9341 datasheet where I found that there are better options to send data.
        There is a second video to the one above where I show about 18x improvement on speed if I did not made any mistakes when I changed the code to work with my STM32F3. I also implemented 16bit SPI data instead of 8 when sending pixel color but that probably did not made almost any difference.
        I liked your code since was simple and easy to understand and modify and included the SPI library.
        My project is open source so all files will be available and your name will stay there. I will just add mine under mentioning that I made changes.
        If you have time to look at my code and make it a bit cleaner that will be great and then you can publish an updated version for others.

        • Sounds fair from you 🙂
          What changes you’ve made in SPI library?

          • electrodacus

            Just small changes there. I needed to change the SPI send to be able to send 8bit data it was always clocking out 16bit data.
            uint8_t TM_SPI_Send(SPI_TypeDef* SPIx, uint8_t data) {
            uint32_t spixbase = 0x00;
            /* Wait for previous transmissions to complete if DMA TX enabled for SPI */
            SPI_WAIT(SPIx);
            /* Fill output buffer with data */
            spixbase = (uint32_t)SPIx;
            spixbase += 0x0C;
            *(__IO uint8_t *) spixbase = data;
            /* Wait for transmission to complete */
            SPI_WAIT(SPIx);
            /* Return data from buffer */
            return SPIx->DR;
            Maybe one or two small changes but I will give you all the files just to make sure it will work for you.

          • What’s the difference between your code and my?

            SPI->DR = data; /* Fill register */

            If you set SPI to 16bit mode, then you have to user TM_SPI_Send16() to send 16bit value.
            Function TM_SPI_Send is designed for 8-bytes values. by default, but you set SPI to 16-bit.

            Ok, I understand you point. By writing as BYTE to data register, SPI will work other way.
            That’s not bad idea at all, if it works.

          • electrodacus

            I send the commands and initialisation as 8bit and it works I checked on oscilloscope.

          • Hi electrodacus, I’m interesting to understand how you have obtained x10 faster.
            The library is very good. but it’s a bit too slow (it’s not a critic marjele,You have made a very good job).
            But for my application, I need more speed.
            can you, electrodacus, explain us your modification ?
            Thanks in advance

          • If you need speed, then use parallel LCD using FSMC or LTDC.

          • OK, I’ll check this point

          • is the LTDC is compatible with nucleo STM32F401RE ?

          • No

          • I have analyze the code of electrodacus :
            I had optimze the Marjele Library by using the technic of dacus.
            Marjele use this one : place de cursor to a position, and then put the pixel color. this is used for pixel, line drawing and of course for rectangle empty/fill, circle.
            I had change a little bit the code without dacus advises : for line, I create a windows for the full line and then send color of each point in continuous. the same method is used for rectangle (not using line draw).
            The different is amazing : in -o0, the display is very quick now, it’s difficult to see the drawing (a little bit, but better).
            in -o1, you can’t see the drawing at all.
            in -ox (superior optimization), it’s quicker, but I encountered some probleme (some pixel missing in the display, the reset and initialisation make some bug on display).
            All my optimization is made without DMA. It can be used very simple (like marjele library).
            Marjele, your base is very usefull, great job.
            Dacus, thanks for your advises.
            I’ll prepare a modified fill to and a template project with the optimize code. Perhaps it can help others too.
            I need to finish my code and I’ll give you links.
            the main changed file is the ili9341.c. I had just reimplement the drawing functions. I have not modified others files (likee SPI, GPIO, etc)
            Futhermore, I had create a function to display a XBM picture, with position, color for bit1 and bit0.
            I need to treat color picture files too. I prepare the code asap.
            Great job Marjele and Dacus. Thanks for your active project. it help me to implement quickly my TFT in my project.

          • I agree with both. Probably I will make some changes here for this lib, but only for these:
            1. Filled rectangle, first select object window then send everything using SPI DMA library
            2. If line is vertical or horizontal then I can do that too.
            3. In other cases, setting window first and then other I think is not so useful.

            Maybe today will make an update, TM SPI DMA library will be needed I think. Will see.

          • for you point 3, it depend on the size and the oriantation of the form you want to draw.
            Each time you draw a line, you send 10 bytes for cursor position + 1 byte for GRAM start.
            for a small form, there’s a minimal impact.
            but for bigger form, it will be great to avoid the method (it’s my opinion, not a critic).
            For example, if you make a fill rectangle of 10×20, you loose, in the better method, 10+1=11 bytes x 10 = 110 bytes.
            the number of bits to draw is 10×20 = 200 bits x 2 bytes per pixel = 400 bytes. your drawnig time is impacted up to 1/4 of the time.

            for the same area but rotated of 90 degree, the result is :
            20 x 11 = 220 bytes.
            the number of bits to draw = 400 bytes. your drawnig time is impacted up to 1/2 of the time.

            I think it’s a good solution to avoid cursor repositionning and optimize basic drawing function (line, rectangle (fill)).
            I have not check the process of string display. I don’t know if the method can be used or not.

            but of course, for certain types of drawing (like circle) it’s difficult to optimize a lot, because computation is necessary and window can be set easily.

          • Well, I don’t know why is different in other LCD orientations.
            LCD supports hardware orientation, so you still send data the same.

          • when I talk about 90 degree, it’s not the LCD orientations, it’s the form orientation on the screen (vertical or horizontal). I considere that the LCD orientation is not modify.
            It’s just about the number of lines you need to draw depending of the form (rectangle vertical or horizontal)

          • A ok, my mistake, sorry.
            Well, I think, that if you set window size, then it doesn’t matter how line is, vertical or horizontal.

            If I set window top left point 10,20 and bottom right 15,30, this would be the same as if I set window like top left = 10,20 and bottom right = 20,25. Rectangle has different orientation but for processing that I think it should be the same. LCD will do it’s job by itself.
            When you go to new line, it’s not needed to specify X coordinate again.

            My opinion is that 🙂

          • Hi Marjele & Dacus,
            I have put the DMA in function. The different with or without is spectacular.

            to summarise quickly, with your library with windowing implementation, each byte on SPI (in my case and configuration) is send in 400ns.
            but due to the code execution between two steps of color pixel transmission we loose 2.7us. during this time the spi does nothing.

            with DMA, the 2.7us are filled with transmission and we gain time.
            we approximatly obtain 7x to 10x more speed (I need to measure it exactly, it just a visual and counting evaluation)

            on my project, displaying xbm files are now very stunning.

            I will prepare a page on my website that explain the difference with the signal views and measuring and a video of each mode.
            just to explain to others…

          • the video show the difference.
            In the demo, there’s no delay and pause. The timing is due to the drawing process.

            I’m preparing a page on my website to explain why.
            I’ll put the link asap.

          • Ok put it. I know what you mean by using dma and why is this, but you can of course, explain to others why is it so.

          • I know that you know what is it 😉 like electrodacus .It’s just for others. I like to share my experience to explain to others.

          • Hi, here you can find my page form explaination :

            http://www.requiem-projects.com/en/ili9341-lcd-driver-stm32f4-dma/

            hope that it will help…

          • Nice work.
            My name is actually Tilen and surname Majerle. Please correct :))

          • Sorry ! I Will correct 😉

          • Hi,

            I’ve done some optimizations in library. You can try it 🙂

          • electrodacus

            Just used Optimization Level -O1 on the initial library and that made thing 2x faster from 84.326 seconds down to 47.207 seconds for the entire test. Adding DMA without optimization -O0 was at 49.150 seconds and with -O1 I get as you see in this video 33.712 seconds.
            All this where done at 40Mhz CPU and 20Mhz SPI and I get about 14.7 frame/second so with 80Mhz CPU and 40MHz SPI I can get close to 30fps good enough for a full frame rate video. I think SPI interface is fast enough no need for parallel in almost any application.

          • Ok, maybe for ILI9341 really no need for parallel.
            What about 640×480 LCD mounted on STM32F439-EVAL board. Do you think you can use SPI only?

          • electrodacus

            It depends on what you need from that LCD. I’m not aware of any 640×480 SPI LCD let me know if you seen one. There is a 480×320 half VGA one and that will work as fast as It works for me now on this 320×240 if you increase the SPI speed from 20 to 40 or 45Mhz (I think 45Mhz is the limit on the F439) I seen some cortex M from Atmel that can run the SPI at the same speed as the CPU (I seen 80Mhz SPI there).
            The limitation is now the SPI speed mostly but up to VGA is possible over SPI. Maybe for higher resolution screens they will use two or 4 SPI lines or integrate HDMI in to microcontrollers. There wont be long before basic microcontrollers will have the capabilities of the current generation smart phone SOC based on the cortex A.
            For my current project 2.2″ is max LCD size I can fit so there is no better option than 320×240 and the speed is more than good for me now (I will probably stay at 40MHz CPU and 20Mhz SPI). Again thanks for making the library available it was a great starting point for me.

          • electrodacus

            Hi Jean, There are a few different things that I changed I explain more in the video description (on youtube there is a show more button under the video and there is a text description).
            The way Majerle and some others implemented drawing any object was sending each point coordinates and point color each time. When I need to fill the screen or draw a rectangle for example is more convenient just to set an active window for the LCD controller memory and then just send the pixel color data the LCD will automatically increment the location from left to right and up down when a row is done. For text speed up I implemented something similar just used a buffer 1k of ram is needed so that you can draw the large 16×26 text 16×26=416 and each pixel has 16bit color then I rounded the buffer to 1k.
            Actually since that video I also implemented DMA and speed things up even more in some cases up to 2x
            I do not have time to make another video right now I’m quite busy with my project. The complete code for my project will be available around October when the product is done.
            You can have about the same speed with SPI interface as you can have with parallel. There is no reason to waste pins with a parallel interface.
            I’m not realy a software guy so you may not like my code almost no comment and not very well organised.

          • Thanks ElectroDacus,
            I had started to read more precisely the datasheet of the ILI9341. I have understood your method by windowing the display and transfer the data.
            I’ll try to implement this method as soon as possible, and adding the DMA like you.
            I’ll give you feedback asap when my code will works.
            Perhaps I’ll probably exchange with you if I need help.
            Thanks again for your explaination.
            For information, I’m developing on Nucleo STM32F401RE with emblocks and FreeRtos

          • electrodacus

            Glad I was of help. I also used 16bit SPI data transfer for pixel color not sure how much that helps if you implement DMA also.
            There is a bit of a problem with DMA I needed to add a delay after the TC (transmission complete flag check) it seems despite the name it represents the fact that the last byte (or I think half word in my case) is ready to be transfered so if SPI speed is much lower than CPU and code compiled with optimization you get artifacts on screen. That delay allows for data to be transfered. Not sure if there is a better solution.

            The code without DMA is here electrodacus.com/SBMS100/SW/SBMS_ILI9341.zip in case you did not see that in the video description.
            Normalcy the objects in my benchmark are the ones that can take this huge speed improvement and things like a horizontal line or circle (not filled) will not have any or little advantage but I also do not need those for my project.

          • Thanks for your code ! I will test it very soon. ^^

          • electrodacus

            I made the modified library available so you can check and implement the changes in yours if you want. I think the speed increase is significant but let me know what you think.
            Here is the new video with a benchmark of the objects that can take advantage of this and the link to library is in the video description https://www.youtube.com/watch?v=4t-ZtKlw0P8
            Ignore the second part of the video benchmark is just the first part.

  • varian w

    Hi , thank you for the library, I made some changes to make it work for STM f10x. I’m curious and feel happy if you can show how to create those fonts libs, because I need bigger fonts. Thank you TM 🙂

  • Hi Marjele, I continue working on lib Optimization and my project.
    I have seen a strange behaviour on the ILI9341.
    Some times, the TFT seem to be not reset correctly : “window” page are not correct, 1 line pixel on the right is place on the left.
    Sometimes it’s work well, sometimes not.
    First I think it’s a problem of my code, -Ox optimization, etc…
    and I have found the problem.
    In your code :

    http://pastebin.com/embed_iframe.php?i=Sq9EPwbS

    the problem is the delay between the RST signal and the SPI RESET ILI9341 command.
    you need to place a delay between this 2lines, to let the device Reset “Hardwarely” before sending SPI command.

    http://pastebin.com/embed_iframe.php?i=275VAqpF

    I have place this delay and I have’nt no more problem now.
    Perhaps it can be a enhancement of your code 😉

    PS : Sorry for the pastebin links, I don’t know how to include code view in message

  • za_el

    Hi,
    Can you share plz the connexion between TFT LCD and STM32F4 discovery board with SPI interface ?

    Thanks in advance

    • You have it!

      • za_el

        really !! where so –‘
        I see only conexion between TFT LCD and STM32F429 board …

        • You think you can use the same?

          Btw..there is also how to change connection if you need 😉

          • za_el

            sorry i can use the same what ?!
            Actually i have STM32F4 board and TFT lcd and i think it possible to have a SPI interface between the both devices… but i have doubt about the connexion …
            Your talking about defines.h files !?

          • This is your last chance!
            So, you have default pinout, which matches F429-Discovery board. OK, but you can use the same pinout if you connect lines to your SPI driver ILI…
            And now..F4-Disco probaby don’t have PF9 pin or maybe more of them but for sure it does not have SPI5.

            And then you have defines which you can easily change in defines.h file.

          • za_el

            Thanks ! and sorry i’m really i begginer in STM32 ^^
            yeah is sure that PF9 doesn’t exist in F4-disco i checked this before, alright so to be sure that i understand you …and to resume the conexion between f429-DISCO and ILI is completly different from F4-DISCO and ILI … altought the have the same pinout –‘ !
            and in your site you don’t defines the changes somewhere ? :p

  • Pingback: Library 18- ILI9341 with LTDC on STM32F429 Discovery - STM32F4 Discovery()

  • Ray

    Is this library “thread safe” for use with RTOS ? ie would it object to being run under a round robin scheduler ?

    • Technically it is not. It uses DMA for data transfer.

  • selfie mug

    i have some question, please help me,
    how to display an image into background with this library? what we must have matrix image like in button_back.h? and how implement that image(matrix) into background?

  • stefan

    hey i also have a little question about this project.

    i always get the same error during building.

    [cc] C:CooCox2definestm_stm32f4_ili9341.c: In function ‘TM_ILI9341_SendData’:

    [cc] C:CooCox2definestm_stm32f4_ili9341.h:148:21: error: ‘SPI5’ undeclared (first use in this function)

    i’ve included every of your h and c files and all the other functions with are necessary. i don’t know what to do. Can you please help me?

    • Well, very useful Coocox uses standard peripheral drivers version 1.0. There is no SPI4,5,6 support because when this version was released, there was no MCUs from ST F4xx with more than 3 SPI peripherals.
      So, download standard peripheral drivers from st.com for F4xx and replace files from coocox in your project.

  • Lee Pui Chung

    I have a question, i am using these codes with a stm32f429 discovery
    but i found that if i used those functions e.g. TM_ILI9341_Puts within the while loop
    the lcd screen won’t do anything. Please help me, thank you.

  • Lee Pui Chung

    Hi, I have a problem when i putting these codes inside my project. My board is STM32F429 Discovery and my project is trying to read temperature with IR sensor. The IR sensor is running on I2C. These codes can work alone but if i add them to my project, functions like “TM_ILI9341_Puts” will keep looping at “while (TM_SPI_DMA_Working(ILI9341_SPI));” inside the while loop. Also, the LCD will not working correctly if i initial it after initialization of I2C. Please help, thank you.

    My codes: http://pastebin.com/DXdbBfHH

  • Jerry Hancock

    Hello, Thank you for posting the above code. I almost gave up several times as I am new to the STM32F4, using Eclipse on a mac, etc. The biggest problem I had was that the stdperiph library 1.6 seems to have some bugs in it. I found a copy of 1.5.1 and after making sure I no longer had old code mixed in (or new considering 1.6.0 was the old), I finally got it to compile, load and run.

    Anyway, wanted to pass this message along with my appreciation.

    Jerry

  • Daniel Ponzo

    tim, trying to connect spi ili9341 to 407 discovery.
    I’ve modified defines.h to match with spi1 and pinspack 1.

    but compiling with keil still sowing 5 errors similar to herebelow:
    quote

    tm_stm32fspitm_stm32f4_spi.c(520): error: #20: identifier “GPIO_AF_SPI4” is undefined
    endquote
    have seen in spi.h your instruction to replace x with 1-6 (speacking about spi)
    how do i do such change? i cannot find the definition of the x value.
    would appreciate your help.
    brgds.
    Daniel.

    • You will need to update standard peripheral drivers. X values should be replaced with 1-6 to match spi peripheral number, so as mentioned, x can be 1,2,3,4,5,6

      • Daniel Ponzo

        still a bit lost…

        • these settings for SPI are not related to your problem.
          Just download Standard peripheral drivers for F4xx from ST.com and you are done. Replace new files with existings and that’s all.

          • Daniel Ponzo

            mthanks Majerle, but still having some bug with rcc.c .
            http://pastebin.com/2NhZC1bD
            what would you suggest.
            daniel
            daniel

          • Christian Julius

            Its doesnt work. I use the latest libs and still got this warning.

          • That’s bad.

          • Christian Julius

            tmlibtm_stm32f4_spi.c||In function ‘TM_SPI4_INT_InitPins’:|

            tmlibtm_stm32f4_spi.c|519|error: ‘GPIO_AF_SPI4’ undeclared (first use in this function)|

            tmlibtm_stm32f4_spi.c|519|note: each undeclared identifier is reported only once for each function it appears in|

            tmlibtm_stm32f4_spi.c||In function ‘TM_SPI5_INT_InitPins’:|

            tmlibtm_stm32f4_spi.c|539|error: ‘GPIO_AF_SPI5’ undeclared (first use in this function)|

            tmlibtm_stm32f4_spi.c||In function ‘TM_SPI6_INT_InitPins’:|

            tmlibtm_stm32f4_spi.c|560|error: ‘GPIO_AF_SPI6’ undeclared (first use in this function)|

            ||=== Build finished: 3 errors, 0 warnings (0 minutes, 2 seconds) ===|

          • WASNT I CLEAR?

            “these settings for SPI are not related to your problem.Just download Standard peripheral drivers for F4xx from ST.com and you are done. Replace new files with existings and that’s all.”

  • Jerry Hancock

    After playing with this code for a while and then integrating the external interrupts from your other fine code, I don’t understand why this display paints so slowly. When watching your code on video, mine is about 4x slower. Ideas?

    thanks again.

    • Hi, check my example 8 on github. Open defines.h file for that project and check my settings for spi prescaler. Also, make sure your pll is on maximal clock.

      • Jerry Hancock

        Ok, prescaling fixed the painting by a factor of 10 or more but now the buttons which I integrated using your code are not working for some reason. I’ll dig into it.

        • Jerry Hancock

          Something is going on and I can’t put my finger on it.

          In my code (extracted from your samples) if I initialize the ILI9341, rotate to portrait, fill the lcd, puts a string and then set the touchdata orientation to portrait, all works fine.

          If I initialize the ILI9341, rotate to portrait, fill the lcd, and then set the touchdata orientation (skipping the puts above), the touch screen functions write the buttons but they don’t respond.

          At first I thought it was related to the prescaler define but while setting that define I took a a write out that I no longer needed.

          It’s almost like there needs to be a slight delay between rotating the LCD and initializing the touch.

          http://pastebin.com/z0i43bvp

      • Jerry Hancock

        So now I can’t get working code again no matter what. The buttons sometimes don’t paint the text within the button. Unplugging the board vs loading and resetting with OCD seems to change things as well. I enable all the buttons in my code (using 5 buttons only) and they don’t work for some reason. I suspect a memory leak or an alignment problem because changing the define for the variable str sometimes makes a difference. At this point I would like to get it back to where the puts was causing the problem as below.

        Any ideas?

      • Jerry Hancock

        I have it working again. It looks like there is a conflict somewhere with the interrupt I was using on PB12. I changed it to PD0 and all is working. I only really need two interrupts so I will go looking to find another.

  • Pingback: ILI9341 LCD Driver + STM32F4 + DMA -()

  • Anoop Kumar

    I am using the same LCD with 8080-1 parallel interface . I am using Landscape mode i.e, 320×240 . If I want to update a specific area do i need to change my coordinates according to the current layout to update to LCD column address register ?? eg I need to right to toop left of 320 x240 i.e, (0,0) what value I need to update to LCD page offset and column address register . Note: I have already changed MAC register to change to Landscape mode

    • Anoop Kumar

      It is not needed .. ty..:)

  • sp

    Hi, can you give me an example for using the LCD in STM32F429. I don’t know what should I put on the defines.h so i get some warnings when i build the project and some errors that says some pins are not defined, Thank you and hope hear you soon. tm_stm32fspitm_stm32f4_spi.c(520): error: #20: identifier “GPIO_AF_SPI4” is undefined
    endquote so i can not build the main.c. I am new in using the STM so i will really appreciate your help.

    • Sounds like you don’t have updated Standard Peripheral drivers, or you are using HAL drivers.
      If problem is first:
      – Update SPL Drivers from ST.com. search for “STM32F4xx Standard peripheral drivers” and download/replace it with existing,
      – If you are using HAL, then this library won’t work for you.

      Anyway, if you are using STM32F429-Discovery board, you might to take a look at my library 18, where LTDC is used to communicate with SDRAM.

      PS: You are using GCC based environment or Keil/IAR?

      • sp

        Hi, i am using a software called Em::Blocks 2.30 i think is a compiler ARM GCC compiler it says… But I have already downloaded the dirvers and I tried a lot of times to add the drivers but i´m still having problems when I debug NOT with your library but with the new drivers there are a lot of files and i don’t know wath files I have to add. There isn´t anny doccument that explains that. Maybe you can help me how to update the pheripheral drivers in a good way or a document or an example. Or maybe is the program!!!!!!! when I change the drivers and debug a blank project it fails.

        Thanks for answering. And sorry if my english is not so good.

        Greetings.

        • Still don’t know what type of library you are using. But if you have HAL, then this lib won’t work. You can try to use CubeMX generator to make code and startup project for you before you start.

          • sp

            Okay thaks i am going to use that CubeMx thaks a lot and i am not using Hal library only the files that appear by defaultl when you make a new project but when I want to replace with new standar peripheral drivers I get a lot of errors I dont understand that library This is all that comes from ST.com

          • divum

            Hi Tilen ,

            please kndly tell me to how create the XBM format ..

            If you know tools please ping me links.

  • Christian Julius

    Hello,

    any isdea whats wrong? I included all libs, have the newest stuff from ST…. but cant compile 🙁

    G:STM32F407STMF407_Displaytmlibtm_stm32f4_ili9341.c:249||undefined reference to `GPIO_SetBits’|

    • Christian Julius

      The compiler can find the implementation of GPIO_SetBits….

      /* Pin definitions */

      #define ILI9341_RST_SET GPIO_SetBits(ILI9341_RST_PORT, ILI9341_RST_PIN)
      #define ILI9341_RST_RESET GPIO_ResetBits(ILI9341_RST_PORT, ILI9341_RST_PIN)
      #define ILI9341_CS_SET GPIO_SetBits(ILI9341_CS_PORT, ILI9341_CS_PIN)
      #define ILI9341_CS_RESET GPIO_ResetBits(ILI9341_CS_PORT, ILI9341_CS_PIN)
      #define ILI9341_WRX_SET GPIO_SetBits(ILI9341_WRX_PORT, ILI9341_WRX_PIN)
      #define ILI9341_WRX_RESET GPIO_ResetBits(ILI9341_WRX_PORT, ILI9341_WRX_PIN)

      • Christian Julius

        Ok, got it.

  • Christian Julius

    Tilen ?

    Please take some minutes for help! :-/ Everything works fine but the display is awful slow. The SPI works only with a few hundred Kilohertz. You can see how the rectanges fill. I tested the lib with the F429 board (without LTDC) and with the F407 Board with diplay attached.
    The core frequency is reported as 168 Mhz. The display can work with frequencies up to e few Mhz I think.

    What is wrong that the SPI is so slow?

    Video: Your library, 407 Board, same configuration, works fine!

    • Send project to my email for f429,will test.

      • Christian Julius

        Ok, I am at work the moment and ssh connection to my computer at home is broken for some reason. Project parameters:

        StderiphLib + CMSIS V 1.6.1
        Your latest libraries
        My Demo application
        Used SPI: #2 on Port B, Pinspack 2 (407) and SPI#5 for F429

        Nothing special……

        The SPI routines contain some “calculations” for Baud Rate. I outcommented them all and tested SPI prescalers from 2 up to 256. Nothing happens.

        • Not sure you heard me. For F429 send project. On F429 is SPI5 used.

          Yeah, nothing special. Special are your settings which I don’t see.

          • Christian Julius

            The F429 project is exactly your demo. 1:1 No “special” settings”. Clearing the screen takes 3 seconds. drawing is “visible”. Rectanges are filled beginning from top to bottom. Display is the one you get in masses from ebay, same look, same pins, same red board.

          • Again..would you mind to send it?
            You have F4 series, and on video if L series. So there are differences!

          • Christian Julius

            Didn’t ypou read? I cant find your email adress here (Impressum?) and I am at work in the office. I will do it in the evening at home. I see you on facebook but you cant send files with it, i guess.

            PS: I have this “L” Board too. Super low Power controller, 80Mhz I guess. The SPI “macro cell” from ARM is the same for all chips.

          • You will have to use a search.

          • Christian Julius

            I took the one from the source code, hope it is valid. Ok, i drive home now during lunch and send you the zipped project. It’s Em::Blocks with startup from Atollic, my own linker scripts….. CU

  • Jacob

    how can I display an int variable on the LCD? I’ve tried to do it with sprintf, adding ‘0’ to the variable (creating an ASCII) but I get weird signs only.

    Here is the code http://pastebin.com/Sw1RCBtj and here is LCD display http://s7.postimg.org/691hmun2z/IMG_20151122_153624.jpg

    • Christian Julius

      sprintf(buf,”%04″,variable)
      TM_ILI9341_Puts(……..);
      For float, you have to add some linker Options:
      -lm
      -u _printf_float
      -u _scanf_float

      • Jacob

        if I do it like you wrote I get empty screen for both “char *buf” and “char buf”

        • And hardfault error.
          Text variable does not have memory assigned.

          Use char tekst[20];

          • Jacob

            Works well now. BTW no error was shown after build.
            Cheers, and thanks a lot for your libraries!

      • Jacob

        so I’ve added this options to the linker http://s1.postimg.org/5syo86i5r/linker.png but on the LCD shown value is “-2147483648” instead of “1.1654”. If it’s relevant I am using Eclipse (OpenSTM32)
        Full code is here http://pastebin.com/SV0QLupQ

  • Dhananjay

    I’m trying to interface ili9341 LCD with STM32F3 discovery board using SPI, I noticed clock signal and data signal on it’s corresponding pins using scope.

    – Issue is i’m not getting data displayed, could please let me know what are the things to be taken care still

    connection between LCD and STM32F3 shown in pic and my code is below

    #include
    #include
    #include
    #include “stm32f30x.h”
    #include “stm32f30x_conf.h”
    #include “stm32f30x_gpio.h”
    #include “stm32f30x_rcc.h”
    #include “stm32f30x_spi.h”
    #include “font.h”
    #include “sys.h”
    uint16_t POINT_COLOR=0xFFFF;

    ////////////////////////////////

    #define ILI9341_RESET 0x01
    #define ILI9341_SLEEP_OUT 0x11
    #define ILI9341_GAMMA 0x26
    #define ILI9341_DISPLAY_OFF 0x28
    #define ILI9341_DISPLAY_ON 0x29
    #define ILI9341_COLUMN_ADDR 0x2A
    #define ILI9341_PAGE_ADDR 0x2B
    #define ILI9341_GRAM 0x2C
    #define ILI9341_MAC 0x36
    #define ILI9341_PIXEL_FORMAT 0x3A
    #define ILI9341_WDB 0x51
    #define ILI9341_WCD 0x53
    #define ILI9341_RGB_INTERFACE 0xB0
    #define ILI9341_FRC 0xB1
    #define ILI9341_BPC 0xB5
    #define ILI9341_DFC 0xB6
    #define ILI9341_POWER1 0xC0
    #define ILI9341_POWER2 0xC1
    #define ILI9341_VCOM1 0xC5
    #define ILI9341_VCOM2 0xC7
    #define ILI9341_POWERA 0xCB
    #define ILI9341_POWERB 0xCF
    #define ILI9341_PGAMMA 0xE0
    #define ILI9341_NGAMMA 0xE1
    #define ILI9341_DTCA 0xE8
    #define ILI9341_DTCB 0xEA
    #define ILI9341_POWER_SEQ 0xED
    #define ILI9341_3GAMMA_EN 0xF2
    #define ILI9341_INTERFACE 0xF6
    #define ILI9341_PRC 0xF7
    #define ILI9341_RST_SET GPIOA->BSRR|=1<BRR |=1<BSRR|=1<BRR |=1<BSRR|=1<BRR |=1<APB2ENR |= RCC_APB2ENR_SPI1EN; //Enabling clock for SPI peripheral
    RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOEEN; //Enabling PA PE
    GPIOA->MODER |= 0x0000A900; //Setting PA5-PA6-PA7 on alternate function and PA4 as output pin
    GPIOA->AFR[0] |= 0x55500000; // We select AFR[0] port GPIOA. Then we put the bits 31-20 to conf AF5 which is 0101 .
    GPIOA->OSPEEDR |= 0x00005400; //10MHz for port A

    //Configuration phase

    SPI1->CR1 |= (1 <CR1 |= SPI_CR1_SSM | SPI_CR1_MSTR | SPI_CR1_SSI; // Software driven and master mode.
    SPI1->CR2 |= SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; //0111: 8-bit for DS
    SPI1->CR1 |= SPI_CR1_SPE; //Enabling

    }
    void TM_ILI9341_SetCursorPosition(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
    {
    TM_ILI9341_SendCommand(ILI9341_COLUMN_ADDR);
    TM_ILI9341_SendData(x1 >> 8);
    TM_ILI9341_SendData(x1 & 0xFF);
    TM_ILI9341_SendData(x2 >> 8);
    TM_ILI9341_SendData(x2 & 0xFF);

    TM_ILI9341_SendCommand(ILI9341_PAGE_ADDR);
    TM_ILI9341_SendData(y1 >> 8);
    TM_ILI9341_SendData(y1 & 0xFF);
    TM_ILI9341_SendData(y2 >> 8);
    TM_ILI9341_SendData(y2 & 0xFF);
    }

    void TM_ILI9341_DrawPixel(uint16_t x, uint16_t y, uint16_t color)
    {
    TM_ILI9341_SetCursorPosition(x, y, x, y);

    TM_ILI9341_SendCommand(ILI9341_GRAM);
    TM_ILI9341_SendData(color >> 8);
    TM_ILI9341_SendData(color & 0xFF);
    }
    void TM_ILI9341_DrawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)
    {
    int16_t f = 1 – r;
    int16_t ddF_x = 1;
    int16_t ddF_y = -2 * r;
    int16_t x = 0;
    int16_t y = r;

    TM_ILI9341_DrawPixel(x0, y0 + r, color);
    TM_ILI9341_DrawPixel(x0, y0 – r, color);
    TM_ILI9341_DrawPixel(x0 + r, y0, color);
    TM_ILI9341_DrawPixel(x0 – r, y0, color);

    while (x = 0) {
    y–;
    ddF_y += 2;
    f += ddF_y;
    }
    x++;
    ddF_x += 2;
    f += ddF_x;

    TM_ILI9341_DrawPixel(x0 + x, y0 + y, color);
    TM_ILI9341_DrawPixel(x0 – x, y0 + y, color);
    TM_ILI9341_DrawPixel(x0 + x, y0 – y, color);
    TM_ILI9341_DrawPixel(x0 – x, y0 – y, color);

    TM_ILI9341_DrawPixel(x0 + y, y0 + x, color);
    TM_ILI9341_DrawPixel(x0 – y, y0 + x, color);
    TM_ILI9341_DrawPixel(x0 + y, y0 – x, color);
    TM_ILI9341_DrawPixel(x0 – y, y0 – x, color);
    }
    }

    int main()
    {
    RCC->AHBENR |= 1<MODER |= 0x55555555;
    SPI_init();
    GPIOA->MODER |=0x00000110;
    GPIOE->BSRR |=1<DR=data;
    //while(!((SPI1->SR & 0x1800)==0x0000));
    while(!((SPI1->SR) & (1<<1)));
    }
    void TM_ILI9341_SendData(uint8_t data)
    {
    ILI9341_WRX_SET;
    ILI9341_CS_RESET;
    TM_SPI_Send(data);
    ILI9341_CS_SET;
    }

    void TM_ILI9341_SendCommand(uint8_t data)
    {
    ILI9341_WRX_RESET;
    ILI9341_CS_RESET;
    TM_SPI_Send(data);
    ILI9341_CS_SET;
    }

    void TM_ILI9341_InitLCD(void)
    {
    /* Force reset */
    ILI9341_RST_RESET;
    TM_ILI9341_Delay(2000000);
    ILI9341_RST_SET;
    /* Delay for RST response */
    TM_ILI9341_Delay(2000000);

    /* Software reset */
    TM_ILI9341_SendCommand(ILI9341_RESET);
    TM_ILI9341_Delay(2000000);
    TM_ILI9341_SendCommand(ILI9341_DISPLAY_OFF );

    ///////////////////////////////////////////////////

    TM_ILI9341_SendCommand(ILI9341_POWERB);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x83);
    TM_ILI9341_SendData(0x30);

    TM_ILI9341_SendCommand(ILI9341_POWER_SEQ);
    TM_ILI9341_SendData(0x64);
    TM_ILI9341_SendData(0x03);
    TM_ILI9341_SendData(0x12);
    TM_ILI9341_SendData(0x81);

    TM_ILI9341_SendCommand(ILI9341_DTCA);
    TM_ILI9341_SendData(0x85);
    TM_ILI9341_SendData(0x01);
    TM_ILI9341_SendData(0x79);

    TM_ILI9341_SendCommand(ILI9341_POWERA);
    TM_ILI9341_SendData(0x39);
    TM_ILI9341_SendData(0x2C);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x34);
    TM_ILI9341_SendData(0x02);

    TM_ILI9341_SendCommand(ILI9341_PRC);
    TM_ILI9341_SendData(0x20);

    TM_ILI9341_SendCommand(ILI9341_DTCB);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x00);

    //////////power control///////////////

    TM_ILI9341_SendCommand(ILI9341_POWER1);
    TM_ILI9341_SendData(0x26);

    TM_ILI9341_SendCommand(ILI9341_POWER2);
    TM_ILI9341_SendData(0x11);

    //////////VCOM/////////////////////////

    TM_ILI9341_SendCommand(ILI9341_VCOM1);
    TM_ILI9341_SendData(0x35);
    TM_ILI9341_SendData(0x3E);

    TM_ILI9341_SendCommand(ILI9341_VCOM2);
    TM_ILI9341_SendData(0xBE);

    //////////MAC//////////////////////////

    TM_ILI9341_SendCommand(ILI9341_MAC);
    TM_ILI9341_SendData(0x48);

    TM_ILI9341_SendCommand(ILI9341_PIXEL_FORMAT);
    TM_ILI9341_SendData(0x55);

    ///////////FRAME Rate///////////////////

    TM_ILI9341_SendCommand(ILI9341_FRC);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x1B);

    /////////// GAMMA///////////////////////

    TM_ILI9341_SendCommand(ILI9341_3GAMMA_EN);
    TM_ILI9341_SendData(0x08);
    TM_ILI9341_SendCommand(ILI9341_GAMMA);
    TM_ILI9341_SendData(0x01);

    TM_ILI9341_SendCommand(ILI9341_PGAMMA);
    TM_ILI9341_SendData(0x1F);
    TM_ILI9341_SendData(0x1A);
    TM_ILI9341_SendData(0x18);
    TM_ILI9341_SendData(0x0A);
    TM_ILI9341_SendData(0x0F);
    TM_ILI9341_SendData(0x06);
    TM_ILI9341_SendData(0x45);
    TM_ILI9341_SendData(0x87);
    TM_ILI9341_SendData(0x32);
    TM_ILI9341_SendData(0x0A);
    TM_ILI9341_SendData(0x07);
    TM_ILI9341_SendData(0x02);
    TM_ILI9341_SendData(0x07);
    TM_ILI9341_SendData(0x05);
    TM_ILI9341_SendData(0x00);

    TM_ILI9341_SendCommand(ILI9341_NGAMMA);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x25);
    TM_ILI9341_SendData(0x27);
    TM_ILI9341_SendData(0x05);
    TM_ILI9341_SendData(0x10);
    TM_ILI9341_SendData(0x09);
    TM_ILI9341_SendData(0x3A);
    TM_ILI9341_SendData(0x78);
    TM_ILI9341_SendData(0x4D);
    TM_ILI9341_SendData(0x05);
    TM_ILI9341_SendData(0x18);
    TM_ILI9341_SendData(0x0D);
    TM_ILI9341_SendData(0x38);
    TM_ILI9341_SendData(0x3A);
    TM_ILI9341_SendData(0x1F);

    /////////DDRAM/////////////////////////////

    TM_ILI9341_SendCommand(ILI9341_COLUMN_ADDR);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0xEF);

    TM_ILI9341_SendCommand(ILI9341_PAGE_ADDR);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x00);
    TM_ILI9341_SendData(0x01);
    TM_ILI9341_SendData(0x3F);

    //TM_ILI9341_SendCommand(0x34);
    //TM_ILI9341_SendCommand(0x35);
    //TM_ILI9341_SendCommand(0xB4);

    TM_ILI9341_SendCommand(0xB7); //entry mode set
    TM_ILI9341_SendData(0x07);

    ///////////Display/////////////////////

    TM_ILI9341_SendCommand(ILI9341_DFC);
    TM_ILI9341_SendData(0x0A);
    TM_ILI9341_SendData(0x82);
    TM_ILI9341_SendData(0x27);
    TM_ILI9341_SendData(0x00);

    TM_ILI9341_SendCommand(ILI9341_SLEEP_OUT);
    TM_ILI9341_Delay(10000000);
    TM_ILI9341_SendCommand(ILI9341_DISPLAY_ON);
    TM_ILI9341_Delay(10000000);
    TM_ILI9341_SendCommand(ILI9341_GRAM);
    }

  • Dhananjay

    I’m trying to interface ili9341 LCD with STM32F3 discovery board using SPI, I noticed clock signal and data signal on it’s corresponding pins using scope.
    – connection between STM32F3-ILI9341:
    MOSI – SDI
    SCK – SCK
    PA2 – RESET
    PA4 – D/C
    PE2 – CS
    – Issue is i’m not getting data displayed, could you please let me know what are the things to be taken care.

  • Christian Julius

    Question: I have this display, which is bigger than the small SPI ones. The same chip. Is it possible to use is with SPI mode? There is a 16 Bit data bus on the one side.

    http://www.ebay.de/itm/121504830137?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT

  • Pingback: Code de la gestion du DMA pour l'affichage sur ili9341 -()

  • John Chou

    Hi Majerle,

    I check the schematic of STM32F429I-Disco and found that the hardware is set to 8080 interface as default. So when you choose the SPI interface, have you changed the voltage of IM[0..3]? Or do I misunderstand something? ( Actually there is a problem in the pic, IM[0..3] should be 1001 instead of 0110 )

    THX~

    • Spi is always active. And if it works then there is no need for modifications.

      With spi you can also set different mode as I do when using ltdc.

  • freetoair

    If anyone tried to connect, or ILI9340 instead of ILI9341? I can not get anything on the screen. I checked all the signals with an oscilloscope and there are here.

  • Zeo

    Hi, May I know how your fonts are being generated? I would like to make bigger fonts for the tft lcd. Kindly advice.

  • Murtaz Naqvi

    hi i am trying to use this library with stm32f4 discovery with the same il9341 LCD i have used SPI 1 can you please help me to solve the issue

  • Mahmoud Ramadan

    thank you for this library
    i have 128×128 st7735 LCD , what are changes i have to make in this library to work with my LCD if it possible ?
    thanx

    • Create a new lib. There are no compatibilities between them.

  • Ibra Slay

    Hi

    thank you a lot for your libraries. could you help me with this error?

    linking…

    STM32F429I_DISCOSTM32F429I_DISCO.axf: Error: L6218E: Undefined symbol GPIO_ResetBits (referred from tm_stm32f4_ili9341.o).

    STM32F429I_DISCOSTM32F429I_DISCO.axf: Error: L6218E: Undefined symbol GPIO_SetBits (referred from tm_stm32f4_ili9341.o).

    STM32F429I_DISCOSTM32F429I_DISCO.axf: Error: L6218E: Undefined symbol TM_GPIO_Init (referred from tm_stm32f4_ili9341.o).

    STM32F429I_DISCOSTM32F429I_DISCO.axf: Error: L6218E: Undefined symbol TM_SPI_DMA_Init (referred from tm_stm32f4_ili9341.o).

    STM32F429I_DISCOSTM32F429I_DISCO.axf: Error: L6218E: Undefined symbol TM_SPI_DMA_SendHalfWord (referred from tm_stm32f4_ili9341.o).

    STM32F429I_DISCOSTM32F429I_DISCO.axf: Error: L6218E: Undefined symbol TM_SPI_DMA_Working (referred from tm_stm32f4_ili9341.o).

    STM32F429I_DISCOSTM32F429I_DISCO.axf: Error: L6218E: Undefined symbol TM_SPI_Init (referred from tm_stm32f4_ili9341.o).

    STM32F429I_DISCOSTM32F429I_DISCO.axf: Error: L6218E: Undefined symbol TM_SPI_SetDataSize (referred from tm_stm32f4_ili9341.o).

    Not enough information to list image symbols.

    • Looks like you did not read post at all.

      • Ibra Slay

        problem fixed!!! thanks

      • Wojtek

        I red this post twice. Where is the answer? I cans see it 🙁

  • tomasz

    Hello, when I run this code:

    while (1) {
    TM_ILI9341_Putc(0,0,’B’,&TM_Font_11x18,ILI9341_COLOR_BLACK,ILI9341_COLOR_WHITE);

    TM_ILI9341_DrawLine(0, 240,320,0,ILI9341_COLOR_BLACK);
    }

    i get line which is decreasing but it should be increasing (should be going from bottom left to top right) , i can’t figure it out – can you help me? i’m attaching photo with the screen.

    http://i.imgur.com/CTNXxDg.jpg

    • 240 and 320 are invalid coordinates!

      • tomasz

        why these coordinates are invalid? if so, could you tell me what coordinates should i enter to get increasing line? (for example from bottom left to top right?)
        I think i tried everyting, just tell me what coordinates should i input and then i will show you the output.
        i already implemented my own draw_line function but I’m curious why your’s is not working for me.

        • 240×320 LCD can’t have pixel number 320 or 240 since pixels starts from 0. So you have 0 – 239 or 0 to 319.

          • tomasz

            yeah, but in function TM_ILI9341_DrawLine you check for overflow so in my opinion it doesn’t matter:

            /* Check for overflow */
            if (x0 >= ILI9341_Opts.width) {
            x0 = ILI9341_Opts.width – 1;
            }
            if (x1 >= ILI9341_Opts.width) {
            x1 = ILI9341_Opts.width – 1;
            }
            if (y0 >= ILI9341_Opts.height) {
            y0 = ILI9341_Opts.height – 1;
            }
            if (y1 >= ILI9341_Opts.height) {
            y1 = ILI9341_Opts.height – 1;
            }

            but it doesn’t matter, if i try with something like that it also print’s decreasing line:
            TM_ILI9341_DrawLine(0, 150,200,80,ILI9341_COLOR_BLACK);

  • batman Simon

    Hello TiLEN, I want to ask about their first 24-bit LCD is stm32f4xx GRB discovery that supports it. If so, I can refer to where. Thank you!

  • Jakub Anioła

    Hey,
    Connecting ILI9341 and STM32f407VG is part of my project for studies at Poznan University of Technology in Poland.
    I spend with friends +20h trying to display anything on LCD without any succes.
    So I will post everything what we have done, maybe if you have time you will give us any adivce 🙂
    1. Download your projects from Github
    2. Download Keil uVision
    3. Open project ILI9341 on Keil and let him download libraries
    4. Change to using STM32F4xxx
    5. Change every file to the newest version avaible on this page
    6. Change defines.h to SPI3 and SPI_Pinspack_3 (cause I use STM32F406VG and that GPIOC pins – 10,11,12 are used there) – http://pastebin.com/dCJUndgd

    And after connecting usb to power supply by usb the LCD only gets brighter and not display anyting.
    If you have any adivce, please!

    • Mohamed Ali Toumi

      I’m in the same case here, any suggestion?

    • I forgot you, sorry. Did you try to increase SPI prescaler? having prescaler set to 2 on (I guess) wires about 20cm long is key to failure.

      • Mohamed Ali Toumi

        i’ve tried all the baudrates prescalar values, and none worked

        • Kiran Kanchi

          found any solution ?

          • Tomasz

            Remember to pull up reset pin! I have connected it to 3V3 after 2 days fighting…

      • Kiran Kanchi

        Hi Tilen , I’m your big fan . love your work .
        what changes should i make to get ili9341 working with stm32f407vg .
        i tried modifying defines.h doesnt seem to work i tried SP1 and 3 Pin pack 1 no luck 🙁

    • Kiran Kanchi

      hey did you find any solution ?
      i have Stm32f407Vg and display isnt working for me as well .

  • davidlucas

    Hi Tilen,

    I’m trying to connect a 3.2″ tft and STM32F429 Discovery but I don’t find anything. All displays that I’ve found are smaller and I need to use 3.2″ with your library. I’ve found this display:

    http://es.aliexpress.com/store/product/Free-Shipping-1pcs-lot-3-2-TFT-LCD-Module-Display-Touch-Screen-Panel-PCB-Adapter-Blue/1280487_2036287115.html?spm=2114.04010208.3.150.aKxkJX&ws_ab_test=searchweb201556_0,searchweb201602_4_10017_10021_507_10022_10020_10009_10008_10018_10019,searchweb201603_1&btsid=8f824ebd-39b7-4f6d-b036-a5a7c8574d67

    but I don’t know if it will work with your library and I don’t where I have to connect D/C (PD13) pin.
    In another case, could you recommend me a 3.2″ tft which it works with your library? I can’t find it.
    King Regards.

    • If you find LCD ILI9341 with 3.2 inch, then you can use it.

  • KamykPL

    Hi again Tilen,
    this time I have an issue with interrupts and this library. When doing some interrupts it seems like LCD has higher priority (interrupts are suspended). How could i change it? Or maybe it’s caused by something else?

    STM32F4-Discovery (407), defines for LCD: http://pastebin.com/ez5EcNw4

    • What is a problem actually?

      • KamykPL

        Simply I ask if there are any interrupts used in this library?
        Because instead of driving my MOSFET’s, the Discovery is refreshing LCD mainly.
        If I executed LCD in main() it worked, but I want to refresh LCD in exact periods of time in interrupts with lower priority.
        Before debuggin I asked You to save my time, cause I don’t know much about DMA and SPI coded by You and generally.

        • Opening fioe you can clearly see i dont use interrupts. You can verify this by checking library and irq handlers if exists.

          And library does not automatically update lcd.

          • KamykPL

            OK, thanks. My code is quite chaotic, so need to debug it.
            I know that LCD is not updated automaticly. Before I did it in while(1) in main(). Now I’m trying interrupts. Cheers

  • alin

    Hello! I have a problem with with sime declarations and i can’t figure it out how to fix it. Is some body that can help me?
    Details in the image.

    • You are missing includes for .h files.

      • alin

        I verified and i have done all it needs to be done, there isn’t another included file. It’s just tm_stm32f4_spi.h and tm_stm32f4_dma.h. Do you think that is another file?

        • Your version of SPL drivers from ST is?

          • alin

            I solved the problems with GPIO and NVIC_initTypeDef fuction. Now i must fix the declared implicitly NVIC_Init function. Do you have any idea?

          • misc.h and .c files.

          • alin

            but for assert_param, you know what files i should include?

          • alin

            Solved. But do you have any idea about redeclaration errors of SPI_InitTypeDef, I2S_InitTypeDef, GPIO_InitTypeDef and DMA_InitTypeDef data structs? and all those warnings? this happens when i try to run the upper code,from main.

  • Martin-Michael Kunkies

    Hello
    I got stuck, where is the definition of DMA_Stream_TypeDef.
    I try to make this with Open STM32

    • stm32f4xx.h

      • Martin-Michael Kunkies

        Thx Majerle But now the compiler is casing an Error
        NVIC_InitTypeDef Where is this definition ?

        • A little search could help.
          misc.h file.

          • Martin-Michael Kunkies

            You did a great Job, but I don’t get it, I don’t have Keil I work with OpenStm Eclipse,
            could you give me a hint how to make it work

          • You dont need keil to get this to work.

          • Martin-Michael Kunkies

            OK, but I need a lot of Independent libraries. Do I miss perhaps a description how to do this.
            I hope i don’t annoy you. Greetings from Frankfurt

          • Don’t understand. What independent libs you need? All libs required are provided here.

      • Martin-Michael Kunkies

        I figured out it’s in misc.h
        but where is misc ?
        You are such a smart boy, I envy you!

  • Matthias

    Hello

    I have used your Library and my goal was to draw some lines on the display. This worked perfectly, until i tried to draw a line from the lower left, to the upper right corner. To be able to do this i had to modify your tm_stm32f4_ili9341.c file:
    I have replaced the following lines in the TM_ILI9341_DrawLine() function:

    /* Check correction */
    /*if (x0 > x1) {
    tmp = x0;
    x0 = x1;
    x1 = tmp;
    }
    if (y0 > y1) {
    tmp = y0;
    y0 = y1;
    y1 = tmp;
    }*/

    dx = x1 – x0;
    dy = y1 – y0;

    with this code block:

    dx = x1 – x0;
    dy = y1 – y0;

    if(dx < 0){
    dx *= 1;
    }
    if(dy < 0){
    dy *= -1;
    }

    Also keep in mind that the following code block will always return 1 since you change the values of x0 and x1 if x0 is higher than x1:

    sx = (x0 < x1) ? 1 : -1;
    sy = (y0 < y1) ? 1 : -1;

    You might need to change your draw line function, to support drawing lines in every direction. If i missunderstood something or did something wrong please let me know 🙂
    Im using the STM32F429I-Discovery

    • Matthias

      if just seen a mistake

      dx *= 1;

      should be

      dx *= -1;

  • ran

    Hello, Is there any example of using parallel port ? Best Regards, Ran

  • anshul

    Hi,
    I have Waveshare Spotpear 3.2 inch RPi LCD V4. It has ILI9341 display controller and XPT2046 touch controller. I am using STM32F4 Discovery Board (MB997C, STM32F407VGT6). I am using your library to interface LCD with this board. I have connected SPI3 with (PB3,4,5) with LCD SPI bus. Nothing is displaying on it. any suggestion/solutions ?

    • This controller has 4 pins to select mode of interface. Maybe your configuration is not for SPI directly on startup.

  • Matias

    Hi Majerle! Great Library!
    I have one question, do you have bigger fonts for this lib? or could you explain me what do i have to put in the data array of the font structure?
    Regards
    Matias