ST7789V3 1.47 Inch LCD Driver
Public API reference for the ST7789V3 display driver
Loading...
Searching...
No Matches
Quick Start

This quick start is specifically for STM32 projects using STM32Cube HAL.

The driver itself is platform-agnostic, but the examples on this page assume:

  • SPI_HandleTypeDef hspi1 is your display SPI peripheral
  • your LCD GPIO pins are already generated by CubeMX
  • you are wiring the driver from an STM32 application such as Core/Src/main.c

What You Need To Provide

Fill a ST7789V3_Config with a small set of platform callbacks. These callbacks are the only STM32-specific layer the driver needs.

Config Field Required STM32 Implementation
spi_write Yes Wrap HAL_SPI_Transmit()
delay_ms Yes Use HAL_Delay
set_cs Yes Wrap HAL_GPIO_WritePin() for chip select
set_dc Yes Wrap HAL_GPIO_WritePin() for data/command
set_rst Yes Wrap HAL_GPIO_WritePin() for reset
LCD_Width Yes 172 for this 1.47-inch panel
LCD_Height Yes 320 for this 1.47-inch panel
State Yes Start with ST7789_STATE_READY
spi_write_dma No Wrap HAL_SPI_Transmit_DMA() if DMA is enabled
set_backlight No Wrap a backlight GPIO if your board exposes one
tx_complete_callback No Optional app callback after DMA success
tx_error_callback No Optional app callback after DMA failure
callback_user_data No Pointer forwarded to DMA callbacks

1. Add The STM32 Callback Functions

These wrappers match the driver interface defined in ST7789V3.h and map directly onto STM32 HAL.

#include "main.h"
#include "ST7789V3.h"
extern SPI_HandleTypeDef hspi1;
int8_t set_cs(GPIO_Pinstate state) {
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, (GPIO_PinState)state);
return 0;
}
int8_t set_dc(Trans_State state) {
HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, (GPIO_PinState)state);
return 0;
}
int8_t set_rst(GPIO_Pinstate state) {
HAL_GPIO_WritePin(LCD_RES_GPIO_Port, LCD_RES_Pin, (GPIO_PinState)state);
return 0;
}
int8_t spi_write(uint16_t len, const uint8_t *pData) {
return (HAL_SPI_Transmit(&hspi1, (uint8_t *)pData, len, HAL_MAX_DELAY) == HAL_OK)
? 0
: -1;
}
Public API for the ST7789V3 SPI display driver.
GPIO_Pinstate
Logical output level used by GPIO control callbacks.
Definition ST7789V3.h:113
Trans_State
Select whether the current SPI byte stream is command or pixel/data content.
Definition ST7789V3.h:121

If your LCD backlight is controlled by a GPIO, add this optional callback and assign it to config.set_backlight. If the backlight is hard-wired on, leave set_backlight as NULL.

int8_t set_backlight(GPIO_Pinstate state) {
HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, (GPIO_PinState)state);
return 0;
}

2. Add The Optional STM32 DMA Hook

Only do this if you want non-blocking SPI transfers.

int8_t spi_write_dma(uint16_t len, const uint8_t *pData) {
return (HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)pData, len) == HAL_OK) ? 0 : -1;
}

When DMA is enabled, STM32 HAL must forward the transfer result back into the driver:

static ST7789V3_Config config;
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) {
if (hspi->Instance == SPI1) {
}
}
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) {
if (hspi->Instance == SPI1) {
}
}
void ST7789V3_DMA_Complete(ST7789V3_Config *config)
Finish a successful DMA transfer and run the completion callback.
Definition ST7789V3.c:559
void ST7789V3_DMA_Error(ST7789V3_Config *config)
Finish a failed DMA transfer and run the error callback.
Definition ST7789V3.c:568
Runtime configuration and hardware binding for one display instance.
Definition ST7789V3.h:199

Without those HAL callbacks, ST7789V3_WriteBuffer_DMA() will start a transfer, but the driver state will never return to ST7789_STATE_READY.

3. Build The Driver Config

This is the minimum STM32 configuration required to bring the panel up.

static ST7789V3_Config config = {0};
static void ST7789_SetupConfig(void) {
config.spi_write = spi_write;
config.spi_write_dma = spi_write_dma; // Set to NULL if DMA is not used
config.delay_ms = HAL_Delay;
config.set_cs = set_cs;
config.set_dc = set_dc;
config.set_rst = set_rst;
config.set_backlight = NULL; // Or set_backlight if your board uses it
config.LCD_Width = 172;
config.LCD_Height = 320;
config.tx_complete_callback = NULL;
config.tx_error_callback = NULL;
config.callback_user_data = NULL;
}
@ ST7789_STATE_READY
Definition ST7789V3.h:165
uint16_t LCD_Height
Definition ST7789V3.h:211
int8_t(* set_rst)(GPIO_Pinstate state)
Definition ST7789V3.h:207
int8_t(* set_backlight)(GPIO_Pinstate state)
Definition ST7789V3.h:208
void * callback_user_data
Definition ST7789V3.h:222
uint16_t LCD_Width
Definition ST7789V3.h:210
void(* delay_ms)(uint32_t milliseconds)
Definition ST7789V3.h:203
volatile ST7789V3_State State
Definition ST7789V3.h:218
int8_t(* set_dc)(Trans_State state)
Definition ST7789V3.h:206
int8_t(* set_cs)(GPIO_Pinstate state)
Definition ST7789V3.h:205
ST7789V3_Callback tx_complete_callback
Definition ST7789V3.h:220
ST7789V3_Callback tx_error_callback
Definition ST7789V3.h:221
int8_t(* spi_write_dma)(uint16_t len, const uint8_t *pData)
Definition ST7789V3.h:202
int8_t(* spi_write)(uint16_t len, const uint8_t *pData)
Definition ST7789V3.h:200

If you are not using DMA, use this instead:

config.spi_write_dma = NULL;
config.tx_complete_callback = NULL;
config.tx_error_callback = NULL;
config.callback_user_data = NULL;

4. Initialize The Display On STM32

Call your peripheral init code first, then initialize the display driver.

int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_GPDMA1_Init(); // Optional if DMA is used
MX_SPI1_Init();
ST7789_SetupConfig();
ST7789V3_init(&config);
InvertDisplay(&config, INVOFF);
FillScreen(&config, BLACK);
DrawString(&config, 16, 16, "Hello STM32", WHITE, &Font_16x16);
while (1) {
}
}
const FontDef Font_16x16
Definition font_16x16.c:1622
void InvertDisplay(ST7789V3_Config *config, Inversion_Mode Inversion)
Enable or disable display inversion.
Definition ST7789V3.c:107
void FillScreen(ST7789V3_Config *config, uint32_t hexcolor)
Fill the entire LCD with a single RGB565 color. e.g take orange convert it to 5 bit 6 bit 5 bit TODO:...
Definition ST7789V3.c:228
void ST7789V3_init(ST7789V3_Config *config)
Initialize the display and apply the default startup sequence.
Definition ST7789V3.c:32
void DrawString(ST7789V3_Config *config, uint16_t x, uint16_t y, const char *str, uint32_t hexcolor, const FontDef *font)
Draw a null-terminated string.
Definition ST7789V3.c:340
#define BLACK
Definition ST7789V3.h:79
#define WHITE
Definition ST7789V3.h:80
void SetRotation(ST7789V3_Config *config, Orientation orientation)
Change the logical display rotation.
Definition ST7789V3.c:295
@ Landscape
Definition ST7789V3.h:156
@ INVOFF
Definition ST7789V3.h:140

5. Optional Application DMA Callbacks

You can also register driver-level completion and error callbacks if your application wants notification after a DMA transfer finishes.

static void OnLcdTxComplete(ST7789V3_Config *display, void *user_data) {
(void)display;
(void)user_data;
}
static void OnLcdTxError(ST7789V3_Config *display, void *user_data) {
(void)display;
(void)user_data;
}
static void ST7789_SetupConfig(void) {
config.spi_write = spi_write;
config.spi_write_dma = spi_write_dma;
config.delay_ms = HAL_Delay;
config.set_cs = set_cs;
config.set_dc = set_dc;
config.set_rst = set_rst;
config.set_backlight = NULL;
config.LCD_Width = 172;
config.LCD_Height = 320;
config.tx_complete_callback = OnLcdTxComplete;
config.tx_error_callback = OnLcdTxError;
config.callback_user_data = NULL;
}

Those callbacks are optional. The required STM32-to-driver bridge is still HAL_SPI_TxCpltCallback() and HAL_SPI_ErrorCallback().

6. Common STM32 Bring-Up Checklist

  • Make sure MX_GPIO_Init() configures LCD_CS, LCD_DC, and LCD_RES as output pins.
  • Make sure MX_SPI1_Init() uses the SPI instance you pass into HAL_SPI_Transmit() and HAL_SPI_Transmit_DMA().
  • If DMA is enabled, make sure the SPI peripheral is linked to a valid DMA channel in CubeMX.
  • If DMA is enabled, make sure the SPI and DMA interrupts are enabled so the HAL callbacks actually run.
  • Set config.spi_write_dma = NULL if DMA is not configured yet.
  • Keep config.State = ST7789_STATE_READY before the first transfer.

Next