Today, in this tutorial, I am going to show you, How to interface a TFT display with STM32. This tutorial will only cover the parallel connection today. For SPI connection, I will write another tutorial soon.
I am using STM32CUBEIDE and STM32F103C8 microcontroller for this purpose.
Before I start, I want to mention that I did not wrote 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.
I will start by creating a project in the CubeMx (or in the CUBEIDE). Here, we need to setup the TIMER to create a delay in microseconds. Below is my setup for the same.
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 the same PORT and in the same order.
For eg -> LCD_D0 -> PB0, LCD_D1 -> PB1……………… LCD_D7->PB7.
But just to show you guys, how to program in random selection of pins, I am choosing some of the Pins in random.The pins selected are as follows:
Once the code is generated, we need to copy the following files into our project:
These files are in the code.zip, you can download at the end of the post.
Next, just open the user_setting.h file. This is where we need to modify the code according to our setup. According to my setup the defines are as follows
You can change them, however you have defined the pins for the LCD connection.
After defining the respective pins, we need to modify the TIMER function to create the delay in microseconds. The default setup is shown below. You can change the Timer handler, if you are not using TIMER1.
Now comes the most important part of the setup. That is, customising the
read_8 functions. Here you need to pay attention to whatever I am going to explain. The
write_8 function is defined as given below
This consists of 2 parts. First, we have to clear all the Pins, that are connected to the TFT as DATA Pins. To clear the Pins, we have to write a HIGH (1) to the higher bits of the respective BSSR register.
As, in my setup, the pins PA5 and PA15 are connected to the LCD D7, and LCD D2. So in GPIOA->BSRR register, only the 5th and the 15th bits are HIGH.
The PB0, PB1, PB3 – PB6 are also connected to the data pins. And that’s why, in the GPIOB->BSRR register, the bits 0,1,3,4,5,6 are set to HIGH.
After the pins are cleared, we have to write the data to the LCD. And to set a pin, we must set the lower bits of BSSR register as HIGH. 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.
Similarly, LCD_D7 is connected to PA5. So to write the data, first we will select the 7th bit of the data (d & (1<<7)), and this time shift it RIGHT by 2 (>>2). This is like subtracting 7-2=5. And that’s where, the D7 is connected to.
The rest of the LCD Pins are connected to the respective Pins of GPIOB, and that’s why we don’t need to shift anything there.
The next part is reading the Pins for the data from the LCD. And we do that by reading the IDR (Input Data Register) of the Respective PORT. The read_8 is defined below
The process here remains the same. Except, we have to first select the GPIO Pin, and than shift it according to the position of the LCD Pin, that it is connected to. In the function above, we are first selecting the PB0 pin, and as it is connected to LCD_D0, we don’t need to shift it anywhere. Same for the PB1 also.
Next, we are selecting PA15, and as this one is connected to the LCD_D2, we need to shift it by 13 to the right ( >>13). This process continues for all other pins too.
After all the Pins work is done, we still need to select the delays according to our clock frequency. As I am using STM32F103C8 at 72 MHz, I am going to uncomment the respective code as shown below.
You still need to uncomment the support for the TFT type that you are using. I am using HX8347
YOU CAN DOWNLOAD FULL CODE AT THE END OF THIS POST
This is it for the setup part. Next we will take a look at some of the functions that we can use.
Some Insight into the CODE
readID( ); reads the ID of the display, and store it in the variable ID.
tft_init (ID); initialise the display with the ID that we read.
fills the entire screen with BLACK colour. It’s more like clearing the display, if you like the BLACK background.
Above are some tests, that LCD is going to perform.
printnewstr prints the string in the given ROW. We can customise the text colour, fonts, size of the string.
scrollup is going to scroll the contents of the display in vertically upward direction.
Here is the Picture from the video