tft display interface with stm32 quotation
Before I start, I want to mention that I did not write this code. This is a PORT from the mcufriend’s arduino code, which can be found HERE. I merely made some changes, so that it can be used with the CubeMx with a little modifications.
Now comes the part for setting up the Pins for the display. As, we are using the parallel connection, there are 8 DATA Pins and 5 CONTROL Pins. It would be really easy, if you connect all the data pins to thesame PORTand in the same order.
According to the Setup, the LCD_D2 is connected to the PA15. So if I want to write the DATA to the LCD_D2 pin, first I will select the 2nd bit of the data (d & (1<<2)), and than shift this by 13 using <<13. This will be like adding 2 with 13 to make a total of 15, and that’s where the LCD_D2 is connected to.
After all the Pins work is done, we still need to select the delays according to our clock frequency. As I am using STM32F103C8 at72 MHz, I am going to uncomment the respective code as shown below.
The STM32 LTDC has a peripheral called LTDC LCD TFT Display Controllerwhichprovides a digital parallel interface(DPI) for a variety of LCD and TFT panels. It sends RGB data in parallel to the display and generates signals for horizontal and vertical synchronization (HSYNC, VSYNC), as well as pixel clock (PCLK) and not data enable (DE) signals:
Horizontal timing signal widths are in units of pixel clocks, while vertical timing signal widths are in units of horizontal scan lines. The HSYNC, VSYNC, pixel clock and not data enable signal polarities can be configured to active high or active low in the LTDC_GCR Global Control Register(not data enable signal must be configured invertedwith respect to the data enable signal in the display datasheet). The datasheet of the panel generally provides the timing parameters for the display:
The LTDC has two layers which can be configured, enabled and disabled independently, each with its own FIFO buffer. Layer order is fixed and layer2 is alway on top of layer1. Layer can be enabled writing the LEN Layer Enable bit in the LTDC_LxCR Layer x Control Register. Each layer gets its data from a framebuffer in memory and the start address is written in LTDC_LxCFBAR Layer x Color Frame Buffer Address Register. The frame buffer contains the display frame data in one of eight configurable pixel format: LTDC_LxPFCR Layer x Pixel Format Configuration Registeris configured to choose the pixel format used to store data into the frame buffer. The available pixel formats are:
Line length parameter is the number of bytes in a line plus three (so the total line length is number of pixels * bits per pixel + 3). These parameters, together with the layer windowing settings, are useful if we want to display part of an image contained in the frame buffer, as I’ll show later.
A constant alpha blending value is configured into the LTDC_LxCACRLayer x Constant Alpha Configuration Register, and controls the alpha blending with the underlying layers. In this case the value 255 (which is divided by 255 by hardware to get a value between 0 and 1) indicates a solid color:
Some configuration registers are shadowed, meaning their programmed values are stored into shadow registers (not accessible to the programmer) and reloaded into the actual configuration registers based on the configuration of the LTDC_SRCR Shadow Reload Configuration Register: if this register is written with the IMR Immediate Reload bit the registers are reloaded immediately (as soon as the IMR bit is set the registers are reloaded), if the Vertical Blanking Reload bit is written the registers are reloaded with the new values during the vertical blanking period (at the beginning of the first line after the active display area). These bits are set in software and cleared by hardware when shadow registers are reloaded:
In this example I use the display on the STM32F429-Discovery board, which is driven by the ILI9341 display controller. The ILI9341 can drive a QVGA (Quarter VGA) 240×320 262,144 colors LCD display. The controller can be configured via SPI (or parallel interface, depending on the panel settings) to use a digital parallel 18 bit RGB interface (since only 6 lines per color channel are wired on the board to the LTDC). Since the display pixel format is less than 8 bit per channel (RGB666 in this case), the RGB display data lines are connected to the most significant bits of the LTDC controller RGB data lines:
To display an image we must convert an image file to an array (possibly a const one, so it can be stored in flash memory) of bytes. To do this I used LCD image converter, a simple but powerful application that can convert a file to a variety of different pixel formats:
Once the image is converted to a byte array the generated header file is included and the array address can be used as the frame buffer starting address in the LTDC_LxCFBAR register. Layer window parameters are configured according to the image size (240 x 320, I rotated the image to fit the display in portrait mode).
The second layer can be enabled as well and its contents drawn on top of layer 1. LTDC can manage transparency using the values in the LTDC_LxCACR Layer x Constant Alpha Configuration Register and LTDC_LxBFCR Layer x Blending Factor Configuration Register: here I used a constant alpha of 255 to obtain a 100% opacity (the value in the constant alpha register is divided by 255 by hardware so for example a value of 128 represents an alpha value of 0.5). Since the layer window is smaller than the display area the default layer background color is set to a transparent black (otherwise the default layer background color is used if the layer window is smaller than the display). The image is 110 x 110 pixels and the pixel format is ARGB8888 (the alpha channel is used to draw transparent pixels). Note that the LTDC_LxCBLR and LTDC_LxCBLNR registers are configured according to the image size: the LTDC always starts fetching data from the address defined in the LTDC_LxCFBAR register. I added the following lines of code to the LTDC_init() function to configure and enable layer 2:
Using two layers and playing with the layer window size and position allows to create simple animations by simply moving the layer window around the frame:
Shadow configuration registers are reloaded each vertical blanking period (after the last line has been drawn) and the code waits for the next frame by polling the VSYNCS flag of the LTDC_CDSR Current Display Status Register, whose bits contain the state of the synchronization signals (high if they’re asserted, no matter the polarity configured). Running the code we get a nice smooth animation:
Double buffer is used when we want the code to write on a frame buffer while another buffer is being read by the LTDC. This avoids corrupting the data being displayed on the screen. The buffers are switched during the vertical blanking period using polling or interrupts.
In this example the framebuffers have a RGB888 color depth and for a 240×320 display that makes 225 KiB of memory for each buffer (3 bytes per pixel x 240 x 320 pixels) so they must be stored in external SRAM (the STM32F429I-DISCOVERY has a 64Mbit external SRAM so we’re good). The FMC Flexible Memory Controller has to be initialized and the address of the two frame buffers has to be configured. Drawing on the framebuffer is a matter of writing the right bytes in order to change the color. Once all pixels are drawn (bytes are written) the buffers are switched and the code can draw the next frame:
Now as soon as a frame is done with, calling LTDC_switch_framebuffer() waits for the vertical synchronization period and swaps the buffers. If the code is faster than the display refresh rate (70Hz in our case) it waits for the LTDC to complete drawing the frame.
I"m looking for a C library that can be used for 16-bit data bus. I have been looking at Github, but the only C libraries I found with 16-bit data bus is not suitable for STM32 or Arduino. Do you know one?
They feature a 2.2" SPI QVGA TFT display as well as a 64-Mbit SPI NOR Flash memory for storing graphic images, texts and texture. The expansion boards also offer a joystick for GUI navigation.
X-NUCLEO-GFX01M1 uses the ST morpho connector and supports only one SPI. It is compatible with the following Nucleo-64 boards: NUCLEO-F030R8, NUCLEO-F070RB, NUCLEO-F072RB, NUCLEO-F091RC, NUCLEO-F401RE, NUCLEO-F410RB, NUCLEO-F411RE, NUCLEO-F446RE, NUCLEO-G071RB, NUCLEO-L053R8, NUCLEO-L073RZ, NUCLEO-L412RB-P, NUCLEO-L433RC-P, NUCLEO-L452RE, NUCLEO-L452RE-P, and NUCLEO-L476RG.
X-NUCLEO-GFX01M2 uses the ST morpho connector and suppports up to two SPIs. It is compatible with the following Nucleo-64 boards, which include the X-NUCLEO-GFX01M1-compatible boards: NUCLEO-F030R8, NUCLEO-F070RB, NUCLEO-F072RB, NUCLEO-F091RC, NUCLEO-F103RB, NUCLEO-F302R8, NUCLEO-F303RE, NUCLEO-F334R8, NUCLEO-F401RE, NUCLEO-F410RB, NUCLEO-F411RE, NUCLEO-F446RE, NUCLEO-G070RB, NUCLEO-G071RB, NUCLEO-G0B1RE, NUCLEO-G431RB, NUCLEO-G474RE, NUCLEO-G491RE, NUCLEO-L010RB, NUCLEO-L053R8, NUCLEO-L073RZ, NUCLEO-L152RE, NUCLEO-L412RB-P, NUCLEO-L433RC-P, NUCLEO-L452RE, NUCLEO-L452RE-P, NUCLEO-L476RG, NUCLEO-WB15CC, NUCLEO-WB55RG, and NUCLEO-WL55JC.
I think a lot of people don"t know how to use it properly, and they are paying too much for displays with a driver chip and even reinforcing the use of modular Nextion-type displays.
From what I understand from this AN, care must be taken to choose the correct clock to match the display clock, and it must also be necessary to use an external RAM memory as a buffer for the display frame.
Therefore, it may be more advantageous to use a driver chip, to avoid a lot of setup with external memory. Since it"s not just a software issue, but also the hardware doesn"t have all the support to perform the direct operation with the TFT display (it doesn"t accept STN either).
I am working on STM32F103ZT6 and with SSD1963. I have connected 480X272 and 320X240 LCD’s. I am initializing SSD1963 with the Init Commands on same pins as you use, but in GPIO mode & not in FSMC mode. The Clock Freq from Crystal is 8MHz and in STM32 acitvating PLL is made to 72MHz. So, Clk Freq for SSD1963 is 8MHz. Hope we should configure the PLL in SSD1963. So below is my Initialisation Sequence details.
Start building your first applications with intuitive, user-friendly menus and dashboards using STM32 ARM Cortex-M3 microcontroller. This board provides a compact high-quality multimedia development platform fordevice.
Highlights. Large 320x240 TFT Color Display with Touch Screen and Stereo MP3 Codec chip with great performance give you true power to build GUI-centric embedded devices. Charge your batteries directly from USB port. No additional electronics, or expensive adapters. You can save pictures, sounds and other media files on microSD memory card and 8Mbit Serial Flash Memory and use it in your application. On-board
Programming. On-board STM32 microcontroller is preprogrammed with fast USB HID bootloader, so it’s ready to work right out of the box. You don’t have to spend a dollar more on programmers. For those who need it, board can also be programmed and debugged using
Compilers. mikromedia for STM32 M3 is fully supported bycompilers for ARM. Compilers come with dozens of examples that demostrate every feature of the board.
GUI design with Visual TFT. Easily create fantastic colourful graphical user interfaces (GUI) for mikromedia in. Even total beginners will be able to create amazing applications.
Start building your first applications with intuitive, user-friendly menus and dashboards using STM32 ARM Cortex-M4 microcontroller. This board provides a compact high-quality multimedia development platform fordevice.
Highlights. Large 320x240 TFT Color Display with Touch Screen and Stereo MP3 Codec chip with great performance give you true power to build GUI-centric embedded devices. Charge your batteries directly from USB port. No additional electronics, or expensive adapters. You can save pictures, sounds and other media files on microSD memory card and 8Mbit Serial Flash Memory and use it in your application. On-board
Programming. On-board STM32 microcontroller is preprogrammed with fast USB HID bootloader, so it’s ready to work right out of the box. You don’t have to spend a dollar more on programmers. For those who need it, board can also be programmed and debugged using
Compilers. mikromedia for STM32 M4 is fully supported byandmikroPascalcompilers for ARM. Compilers come with dozens of examples that demostrate every feature of the board.
GUI design with Visual TFT. Easily create fantastic colourful graphical user interfaces (GUI) for mikromedia in. Even total beginners will be able to create amazing applications.
MCUFRIEND_kbv works out of the box with every "Mcufriend style" parallel Shield on a Nucleo. i.e. it supports more controllers than TFT_eSPI. But TFT_eSPI is more sophisticated and probably faster.
As I said. I don"t have the Waveshare Shield. It is definitely convenient to plug a Shield into a Nucleo. I would expect it to run pretty fast with TFT_eSPI. So I am wondering what you have done in your User_Setup.
It is unfortunate that I do not want to buy a Waveshare. I can probably test most other display types. (on AVR, Due, Nucleo, Teensy, ESP8266, ESP32, RPi Pico, ... targets)
Regarding Red SPI displays and Shields. I mount headers and solder wire routeing on a custom ProtoShield. This means that I can run different displays on different targets.
You will see that most of the Display contributors have similar arrangements. i.e. Protoboard or ProtoShields that receive the popular TFT, OLED, GLCD, ...