- MCU: STM32F446 (bare‑metal, register access)
- Display: ST7735 1.8" TFT (128x160) over SPI
- Library files:
src/TFT_ST7735.h,src/TFT_ST7735.cpp,src/fonts.h,src/fonts.c - Example app:
src/main_tst.cpp(basic drawing demo)
This README documents how to use the ST7735 driver: initialization, public API, parameters, return values, possible error conditions, and example usage. It also outlines a midterm project concept built on this driver.
- Wiring (STM32F446 → TFT)
PA5→SCKPA7→MOSIPA3→CSPA4→DC/A0PA6→RSTVCC/GNDper display datasheet
- Clocking: SPI1 runs at ~1 MHz (
BR=011→ fPCLK/16). Adjust inconfSPI()if needed. - Screen geometry:
SCREEN_WIDTH=128,SCREEN_HEIGHT=160. Color format: RGB565 (16‑bit).
The constructor configures RCC, GPIO, and SPI via config(). Call INIT_FN() once to reset and send the full ST7735 init sequence.
#include "TFT_ST7735.h"
int main() {
TFT_ST7735 tft;
tft.INIT_FN();
tft.FillScreen(COLOR_BLACK);
while (1) {}
}-
void INIT_FN()- Initializes the TFT: hardware reset, sends init commands, sets color mode and addressing.
- Parameters: none
- Returns: none
- Errors: If SPI is misconfigured or pins/wiring are incorrect, the screen may remain blank.
-
void FillScreen(uint16_t color)- Fills entire screen with
color(RGB565). - Params:
color(e.g.,COLOR_BLACK) - Returns: none
- Errors: none; internally clips to screen bounds.
- Fills entire screen with
-
void FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)- Draws a filled rectangle with top‑left at
(x,y). - Params:
x,y(pixels),w,h(size),color(RGB565) - Returns: none
- Errors: If the rectangle exceeds bounds, the function clips to fit. If
x>=SCREEN_WIDTHory>=SCREEN_HEIGHT, it returns early.
- Draws a filled rectangle with top‑left at
-
void DrawPixel(uint16_t x, uint16_t y, uint16_t color)- Draws a single pixel.
- Params:
x,y,color - Returns: none
- Errors: No explicit check; writing outside set window would be ignored. Prefer passing valid coordinates.
-
void WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor)- Renders a character using the provided bitmap font.
- Params: position
(x,y), ASCIIch,font(Font_7x10,Font_11x18,Font_16x26),color,bgcolor. - Returns: none
- Errors: Character codes below 32 are not supported; font indexing assumes
ch >= 32.
-
void WriteString(uint16_t x, uint16_t y, const char* str, FontDef font, uint16_t color, uint16_t bgcolor)- Renders a zero‑terminated string left‑to‑right, advancing by
font.widthper character. - Params:
(x,y),str,font,color,bgcolor - Returns: none
- Errors: No bounds clipping beyond what per‑character drawing performs; strings can extend off‑screen.
- Renders a zero‑terminated string left‑to‑right, advancing by
-
void WriteData(uint8_t* data, uint16_t size)- Sends a data buffer with DC set to data mode. Useful for low‑level operations.
- Params:
datapointer,sizebytes - Returns: none
- Errors: If SPI is busy, write waits; incorrect size/pointer leads to undefined behavior.
COLOR_BLACK, COLOR_WHITE, COLOR_RED, COLOR_CYAN, COLOR_MAGENTA, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_PINK, COLOR_PURPLE, COLOR_ORANGE.
Defined in fonts.h:
typedef struct {
const uint8_t width;
uint8_t height;
const uint16_t *data;
} FontDef;
extern FontDef Font_7x10, Font_11x18, Font_16x26;Minimal demo similar to main_tst.cpp:
#include "TFT_ST7735.h"
int main() {
TFT_ST7735 tft;
tft.INIT_FN();
tft.FillScreen(COLOR_WHITE);
tft.FillRectangle(10, 10, 50, 30, COLOR_BLUE);
tft.DrawPixel(20, 20, COLOR_RED);
tft.WriteString(5, 50, "Hello", Font_11x18, COLOR_BLACK, COLOR_WHITE);
while (1) {}
}- No display output: Check
CS/DC/RST/SCK/MOSIwiring and 3.3V power. EnsureINIT_FN()is called after constructor. - Garbage/tearing: Verify SPI mode and timing; current setup uses 8‑bit frames and software‑managed DC/CS.
- Out‑of‑bounds coords:
FillRectangleclips;DrawPixelassumes valid coordinates. - Blocking writes: SPI polling waits until
TXEandBSYare clear; operations are synchronous.
INIT_FN()drivesRST, assertsCSonce, and pushes an encoded init sequence (init_cmd[]) throughWriteCommand(uint16_t*, uint16_t)which multiplexes data/commands via bit 8 in the 16‑bit entries.SetAddressWindow(x0,y0,x1,y1)issuesCASET,RASET,RAMWRand prepares subsequent data writes.- GPIO and SPI configuration live in
confRCC(),confGPIO(),confSPI(), called byconfig()in the constructor.
- Power the board, connect TFT per wiring above.
- Flash the firmware. Verify startup screen and subsequent updates every sampling interval.
- Uses polling; CPU is busy during large fills and string rendering.
- No DMA; SPI throughput is limited.
- No clipping for
WriteString; text can run off‑screen. - Fixed rotation/memory access settings in init sequence.
- Add SPI DMA for faster area fills and text drawing.
- Add text clipping and word‑wrap utilities.
- Support multiple rotations and offsets.
- Double‑buffer drawing primitives; batch pixels.
- Add drawing primitives: lines, circles, images (bitmaps).
File: src/main_osc.cpp
- Purpose: Demonstrate a functional prototype that reads an analog sensor via
ADC1and plots the sampled waveform live on the ST7735, behaving like a simple oscilloscope. - Initialization:
conf_osc()sets up HSE and PLL for higher system clock, configuresADC1onPA0(analog), starts continuous conversion.Screen1.INIT_FN()initializes the TFT.
- Operation:
- Clears the drawing area, draws axes (X and Y) using
FillRectangle. - In the loop, reads
ADC1->DR, scales the reading (>>5) to 7‑bit range for the 128‑pixel X axis. - Increments a vertical index
iterativeas time; plotsDrawPixel(adc_val+3, iterative+3, COLOR_CYAN). - When
iterativereaches 145 rows, clears the area and restarts, creating a scrolling plot.
- Clears the drawing area, draws axes (X and Y) using
- Wire a sensor or signal source to
PA0(e.g., potentiometer between 3.3V and GND with wiper toPA0). - Connect the TFT per wiring section.
- Build and flash the firmware that uses
main_osc.cppas the entry point. - Observe the cyan trace scrolling vertically; adjust the signal and see horizontal movement corresponding to amplitude.
- Sampling is continuous and untriggered; the vertical axis is time index, not scaled to real units.
- No horizontal clipping or scaling beyond a simple right‑shift; signal mapping is coarse.
- Screen clears every 145 rows; no buffer or persistence.
- CPU performs polling for SPI; large draws are blocking.
- Add triggers (rising edge) and horizontal/vertical scaling controls.
- Implement SPI DMA for faster pixel plotting.
- Add grid/labels and numerical readouts (min/max/mean).
- Use a ring buffer to plot without full clears; add decimation.