This documentation covers a STM32 NUCLEO-F439ZI tutorial project that drives Adafruit's RA8875 driver board and 7-inch 800x480 TFT display over SPI, using two reusable STM32 HAL libraries instead of code embedded in the project: STM32_GFX (a port of Adafruit GFX) and STM32_RA8875 (a port of Adafruit_RA8875). It is the library-based successor to the earlier RA8875 tutorial, which carried a hand-converted copy of the Adafruit sources.
Project Overview
The firmware demonstrates:
- Creating an Adafruit_RA8875 object from C++ with only an SPI handle and two GPIO pins (chip select and reset), and starting the controller with Adafruit_RA8875::begin(), which checks the chip ID (0x75)
- The RA8875's hardware drawing commands (fills, lines, rectangles, circles, ellipses, triangles, curves) and its built-in text mode, exercised by two demonstration routines, see testLCD
- Reaching C++ from the plain-C CubeMX
main.c through two C-callable functions, initTest and testLCD, declared in entryPointCPP.hpp
Project-Level Documentation
Hardware
Tested on a breadboard with a NUCLEO-F439ZI:
| RA8875 board | NUCLEO-F439ZI | Notes |
| Vin | +5V | |
| GND | GND | |
| SCK | PA5 | SPI1_SCK |
| MISO | PA6 | SPI1_MISO |
| MOSI | PA7 | SPI1_MOSI |
| CS | PB6 | GPIO output, label RA8875_CS |
| Rst | PC7 | GPIO output, label LCD_RESET |
| Wait, Int, LITE, 3Vo | not connected | WAIT and INT are not used |
Debug output goes to a USB-to-serial adapter on USART1 (PA9 transmits, PA10 receives) at 19200 baud: printf() is redirected there by the pre-build scripts.
What the firmware does
- Start-up (main.c). The terminal screen is cleared, then initTest creates the display object with the SPI1 handle, the CS pin and the RESET pin and starts it. On success it prints "RA8875 Found"; if the chip does not answer with 0x75 it prints a message and stops in the error handler. The library switches the SPI clock itself: it starts at the slowest prescaler (about 350 kHz from SPI1's 90 MHz clock) while the controller's PLL comes up, then runs at the fastest setting not above 4 MHz (2.8 MHz here).
- Main loop. Forever, the graphics demo (testLCD with
true) runs, then the text demo (false), each followed by a pause, with progress printed on the terminal.
- Reset. The firmware does not toggle the RESET pin itself. Adafruit_RA8875::begin() holds it low for 100 ms, releases it and waits another 100 ms.
Differences from the earlier tutorial's code
- The constructor takes the CS and RESET port and pin, not
main.h macros hidden inside the library.
- The earlier hand-written
delay() counted microseconds. The libraries use Adafruit's millisecond delay() (HAL_Delay()), so their waits are the original's and the demos pause for real milliseconds.
- SPI speed switching and the controller reset happen inside the library; main.c no longer re-initialises SPI1.
- The optional WAIT pin is not wired and not used. In the earlier tutorial that pin was driven high by the firmware, so its polling never waited.
Things to know
- Backlight and PWM. The PWM1 setup calls turn on the RA8875 chip's PWM output, but on Adafruit's driver board the backlight is controlled through the board's separate
LITE pin. With LITE unconnected the backlight stays on and the PWM sweep in the graphics demo changes nothing visible, so the sweep is compiled out unless PWM is defined at build time.
- No SPI error checking. The library does not check the HAL return codes of its SPI transfers, so a failed transfer shows up as a blank or garbled display. initTest checks the chip ID, which catches most wiring and SPI-setting mistakes at start-up.
- Not thread-safe. One display object is shared by the demo functions, and each drawing call is several separate SPI transactions; see the notes on initTest and testLCD.
- Build. The
stm32-cubeide-scripts pre-build step edits main.c and main.h on each build (the printf redirect, the error handler and full assert). The libraries are git submodules; clone with git clone --recurse-submodules.