Introduction

I recently worked on a project where I integrated an ILI9341 TFT display with touch functionality into an STM32F103RB board. The goal was to display text and handle touch events, such as clicking buttons, while ensuring the display orientation could be changed by a button press. Here’s a detailed walkthrough of the process.

 

 

Step 1: Setting Up the Hardware

Components:

  • STM32F103RB Nucleo-64 board
  • ILI9341 TFT display with touch (SPI interface)
  • Connecting wires

Connections:

ILI9341 Pin Nucleo-64 Pin
VCC 3.3V
GND GND
CS PA8
RESET PA10
DC/RS PA9
MOSI PB15
SCK PB13
LED 3.3V
MISO PB14
T_IRQ PA7
T_DO PB14
T_DIN PB15
T_CS PB4
T_CLK PB13

Step 2: Initializing the STM32 Project

I started by creating a new STM32 project in STM32CubeIDE and selecting the STM32F103RB Nucleo-64 board.

Clock Configuration: I configured the clock to run at 72 MHz using the High-Speed External (HSE) oscillator and the Phase-Locked Loop (PLL).

Step 3: Configuring Peripherals

SPI2 Configuration:

  • Mode: Master
  • Data Size: 8 Bits
  • CLK Polarity: Low
  • CLK Phase: 1 Edge
  • NSS: Software
  • Baud Rate Prescaler: 8
  • First Bit: MSB

UART2 Configuration:

  • Baud Rate: 115200
  • Word Length: 8 Bits
  • Stop Bits: 1
  • Parity: None
  • Mode: TX/RX

GPIO Configuration: I configured the necessary GPIO pins for SPI communication, the display control pins (CS, DC, RESET), and the touch controller pins (T_CS, T_IRQ).

Step 4: Writing the Code

Main Code: I wrote the main application code to initialize the peripherals, configure the display, and handle touch events. Here’s the main part of my main.c file:

#include "main.h"
#include "fonts.h"
#include <stdio.h>

SPI_HandleTypeDef hspi2;
UART_HandleTypeDef huart2;
volatile uint8_t display_orientation = 1; // Start with landscape mode

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI2_Init(void);
static void MX_USART2_UART_Init(void);
void ILI9341_WriteCommand(uint8_t cmd);
void ILI9341_WriteData(uint8_t data);
void ILI9341_Init(void);
void ILI9341_SetAddressWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void ILI9341_FillScreen(uint16_t color);
void ILI9341_DrawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bgcolor, uint8_t size);
void ILI9341_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgcolor, uint8_t size);
void ILI9341_SetOrientation(uint8_t orientation);
void XPT2046_Init(void);
uint16_t XPT2046_Read(uint8_t addr);
void XPT2046_GetTouchCoordinates(uint16_t *x, uint16_t *y);
void CheckTouch(void);
void DrawButton(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const char *label, uint16_t color);
void DrawTouchPoint(uint16_t x, uint16_t y, uint16_t color);

int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI2_Init();
MX_USART2_UART_Init(); // Initialize UART

HAL_UART_Transmit(&huart2, (uint8_t*)"UART Initialized\r\n", 18, HAL_MAX_DELAY);

ILI9341_Init();
HAL_UART_Transmit(&huart2, (uint8_t*)"ILI9341 Initialized\r\n", 21, HAL_MAX_DELAY);
XPT2046_Init();
HAL_UART_Transmit(&huart2, (uint8_t*)"XPT2046 Initialized\r\n", 21, HAL_MAX_DELAY);

display_orientation = 1; // Set to landscape mode
ILI9341_SetOrientation(display_orientation);
HAL_UART_Transmit(&huart2, (uint8_t*)"Orientation Set\r\n", 17, HAL_MAX_DELAY);
ILI9341_FillScreen(0x0000); // Clear screen
HAL_UART_Transmit(&huart2, (uint8_t*)"Screen Cleared\r\n", 16, HAL_MAX_DELAY);

// Draw buttons in landscape mode
DrawButton(20, 180, 140, 40, "Click Me", 0xF800); // Red button at (20, 180)
DrawButton(160, 180, 140, 40, "Clear", 0x07E0); // Green button at (160, 180)
HAL_UART_Transmit(&huart2, (uint8_t*)"Buttons Drawn\r\n", 15, HAL_MAX_DELAY);

while (1) {
CheckTouch();
}
}

 

Helper Functions: I implemented helper functions for initializing the display, handling touch events, and drawing buttons and text.

Step 5: Testing and Debugging

UART Debugging: I used UART to transmit debug messages to ensure each initialization step was completed successfully. This helped me verify the initialization of UART, SPI, the display, and the touch controller.

Button Press Handling: I configured a button press to change the display orientation and redraw the screen content accordingly.

Touch Event Handling: I added functions to handle touch events, including drawing touch points on the screen and detecting button presses.

Conclusion

By following these steps, I successfully integrated the ILI9341 display with touch functionality on the STM32F103RB board. The display now correctly handles orientation changes and touch events, providing a responsive and interactive interface.

This project was a great learning experience in working with displays and touch interfaces on microcontrollers, and the use of UART for debugging proved invaluable in troubleshooting and ensuring the system’s functionality.