stm32f429 tft lcd ili9341 free sample

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.

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.

stm32f429 tft lcd ili9341 free sample

TM_ILI9341_Puts(10, 100, "Bottom buttons work\nonly if red led is turned on.\nYou can toggle red\nled with Button 1.", &TM_Font_7x10, ILI9341_COLOR_BLACK, ILI9341_COLOR_GRAY);

TM_ILI9341_Puts(10,100,"Bottom buttons work\nonly if red led is turned on.\nYou can toggle red\nled with Button 1.",&TM_Font_7x10,ILI9341_COLOR_BLACK,ILI9341_COLOR_GRAY);

stm32f429 tft lcd ili9341 free sample

The LCD I am using is a 2.8″ TFT LCD with SPI communication. I also have another 16-bit Parallel TFT LCD but it will be another story for another time. For this post, let’s focus on how to display what you want on the 2.8″ LCD. You can find all details about this LCD from this page:http://www.lcdwiki.com/2.8inch_SPI_Module_ILI9341_SKU:MSP2807

First thing first, this LCD use SPI as the main communication protocol with your MCU. For STM32 users, HAL Library has already implemented this protocol which makes this project easier for us. But, a little knowledge about this protocol does not hurt anyone. SPI is short for Serial Peripheral Interface which, aside from two data lines, also has a clock line and select lines to choose between devices you want to communicate with.

This LCD uses ILI9341 as a single-chip SOC driver for a display with a resolution of 240×320. More details can be found in the official document of ILI9341. But the most important thing is that we have to establish astart sequencein order for this LCD to work. The “start sequence” includes many other sequences which are also defined in the datasheet. Each sequence starts when you send a command to ILI9341 and then some parameters to follow up. This sequence is applied for all communication between MCU and ILI9341.

For this project, I recommend using theSystem Workbench for STM32for coding and building the code. After installing and open the program, go to the source code you have just downloaded and double click the.cprojectfile. It will automatically be open in your IDE. Then build the program by right click on the folder you just open (TFTLCD) and chooseBuild Project. Wait for it to finish and upload it to the board by right clicking the folder, choose Run As and then clickAc6 STM32C/C++ Application. And that’s it for running the example.

The most important library for this project is obviously the ILI9341_Driver. This driver is built from the provided source code in the lcdwiki.com page. I only choose the part that we need to use the most in many applications like writing string, displaying image and drawing symbols. Another library from the wiki page is the TOUCH library. Most of the libraries I got from the Internet were not working properly due to some adjustments to the original one.

To draw symbols or even display images, we need a “byte array” of that image or symbol. As an illustration, to display an image from a game called Transistor, I have a “byte array” of that image stored in a file named transistor.h. You can find this file in the link below. Then, I draw each pixel from the image to the LCD by adding the code in the Display_Picture() function in the Display folder.void Display_Picture()

stm32f429 tft lcd ili9341 free sample

I"m using this library but the problem is that I get only two colors at my LCD screen. Black and Purple. That"s because this library is made for 8-bit databus.

stm32f429 tft lcd ili9341 free sample

STMicroelectronics has spent last couple of years developing their embedded graphics framework called TouchGFX. This very powerful graphics engine makes it possible to include snazzy, smartphone-like screens and widgets into the embedded application, what I feel like becomes defactoa standard nowadays. Along with it, they shipped a lot of dev boards and reference designs, that cover various LCD interfaces and graphical demo applications. While the original documentation as well as the demo applications are truly rich in content, many people, including myself, struggled to run this fantastic piece of software on a custom made setup. Especially on the setup that doesn’t meet specific graphics requirements, such as a dedicated LCD interface, a ton of RAM, high clock frequency, RTOS, etc.

For the display, I had a “standard” Aliexpress ILI9341 board with 320×240 TFT LCD. Additionally, the board includes a clone chip of XPT2046, a resistive touchscreen controller. The board came preconfigured in SPI interface, different for touchscreen and display. Now, the important part was to have a working library for both of these components. Luckily, the ILI9341 is a rather popular add-on in hobbyist community, so there were plenty available. I went for the one from this repository here. Whatever you use, make sure that it implements the DMA based SPI data transfer, and window-based rendering, i.e. that you can define only a part of the screen to be drawn. This is what official documentation describes as a Board Bring-Up. In my library, these would be functions called ILI9341_SetWindow() and ILI9341_DrawBitmap().

handle framebuffer transfer to display – this is the most tangible part of the AL, how to actually invoke all those transfer functions from my ILI9341 library.

In other words, this means we need to implement sync signaling to the engine, signaling from the user inputs (buttons or touchscreen), and most importantly, transfer to the LCD. Let’s see how to do that.

Since the graphics engine works cyclically, we need some time base, obviously. If we were using an RTOS, there would be some kind of tick that would take care of TouchGFX tasks. In my simple project, there is no RTOS used, so I need to figure something else out. Ideally, the LCD would signal when the transfer is done. But ILI9341 doesn’t do that, so I decided to configure the STM32 timer to call OSWrappers::signalVSync periodically. But how often? Hmm, since there is no way of knowing, I decided to take some reasonable value that is longer than typical SPI transfer, and short enough for pleasant 30 Hz framerate experience. SPI on STM32F411RE has something of 50 MHz clock, meaning that transfer of 150kB framebuffer would take cca 24ms. So, the timer should trigger an interrupt an invoke the signalVsyncevery 24 – 30ms. On 100MHz clock, the timer would require something like 30000 counts.

When the engine is done rendering, i.e. when the data is written into the framebuffer, it is up the AL to transfer the data to the LCD. It takes a couple of steps to do that. First, we need to check if something is already transferring. If not, we need to invoke the actual transfer functions. Let’s see how it looks like in the source code.

Now the key part – transferring the block to the LCD by implementing the function touchgfxDisplayDriverTransmitBlock(). The implementation should consider writing the data in form of window-based pixel data. So, ILI9341 library should have something that lets user define the window of the screen to write to. My implementation looks like this:

It looks very similar to theflushFrameBufferfunction. But, when to call it? Great question! We know that ILI9341 library uses DMA to feed the data to the LCD. Now, when the DMA is finished, an HAL_SPI_TxCpltCallbackautomatically invoked and given to the user to clean up the data. This is what I did:

stm32f429 tft lcd ili9341 free sample

IMPORTANT The touchscreen has a maximum frequency of 2MHz, which is probably slower than you want your TFT SPI clock. So in the routine that reads touch coordinates (ili9341_touch_pressed_t ili9341_touch_coordinate(ili9341_t *,uint16_t *,uint16_t *) in ILI9341/ili9341.c), make sure to adjust the lines that modify the SPI clock so that your baud rate is less than 2MHz before communicating with the touchscreen (e.g. MODIFY_REG(lcd->spi_hal->Instance->CR1, SPI_CR1_BR, SPI_BAUDRATEPRESCALER_128)), and then restored to whatever setting you use here immedaitely afterwards. See the comments in that source file for both locations.

If using the touchscreen, you will probably want to set Hardware NSSP=Disabled (slave/chip-select) in favor of a software implementation, since you will need one signal for the TFT and a separate one for the touchscreen. Any two unused GPIO digital output pins will work.

If using the touchscreen, override the EXTI callback (void HAL_GPIO_EXTI_Callback(uint16_t)) somewhere in your application code and call ili9341_touch_interrupt(ili9341_t *) from inside that callback.

stm32f429 tft lcd ili9341 free sample

Seems interesting UGUI. However for example for the controller ST7586S have any examples of LCD functions to associate with UGUI? If you have made and canst send to me …

AchimAs we"re already talking Microchip, what would be necessary to get a Pic32MZ2048ECH144 and HX8238-A based display to use µGUI?First of all you have to connect the TFT DPI Interface to the PIC. Then initialize the internal DPI Interface of the PIC. After that you only have to write a Pset-function to use uGUI. Hope this helps! By the way: which hardware platform do you use? BR Achim

At first i would like to congratulate you for this great library/project. I tested it in the STM32F429 Discovery and liked a lot. So, I would ask if you are interested in creating an adaptation layer for an event manager based on RTOS services. I beleive that through RTOS semaphores, queues and timers it is possible to better manage the CPU resources. I started myself a GUI event handler, as you can see here:

Starting with your example of uGFX 3.0 on Stm32f429-Discovery (embd LCD removed) i have changed only screen dimensions to the ltdc.h in order to make it all work and so on it"s a really good result.

Nice job on the uGUI! I"m currently experimenting with it, I had an stm32f429 discovery board so could start right away with your example project in CoIDE.

i really wonder about your gui. it is very simple to use. i want to draw a image on my lcd. i also done by using your library with given example image. now i want to convert image to header file. can you suggest any software to do that.Hi Arun, I think there is a conversion utility on the ST microelectronics page. I can’t remember the name, but I’m sure there is one. BR Achim

I tried, but I can not force to work my 240×128 display with T6963C controller . Could you please send me the code to this: 240×128 LCD | Driver: T6963C | Interface: 8080

I"ve set it up on an STM32L100RCT6 with an 128×64 glcd, and everything works like a charm, except the UG_DrawLine() function, which seems to always draw a falling line, no matter how the arguments are arranged