How to port uCGUI with STM32?
Here’s a practical, battle-tested checklist for porting uC/GUI (SEGGER emWin) on STM32. It works whether you use raw SPI LCDs (e.g., ST7735/ILI9341) or LTDC/DMA2D panels on F4/F7/H7.
0) Prereqs
-
Tooling: STM32CubeIDE (or Keil/IAR), CubeMX for clock/pin init.
-
uC/GUI (emWin) package:
-
For many STM32 MCUs, ST ships STemWin (a licensed emWin build).
-
Otherwise, use a SEGGER emWin library matching your compiler/CPU.
-
-
BSP drivers: Your LCD (SPI/LCD controller or LTDC) + optional touch (I²C/ADC).
1) Add emWin/uC-GUI to the project
-
Include core sources/libs (GUI/, WM/, LCD/, etc.) or prebuilt library from STemWin.
-
Add config stubs (typically):
-
GUIConf.c→ memory allocator configuration -
LCDConf.c(a.k.a.LCD_X_Config) → display driver & layer config -
GUI_X.c→ timing, multitasking hooks (OS or bare-metal)
-
Project include paths should point to emWin headers; link the right library variant (e.g., Cortex-M4F/Thumb).
2) Allocate GUI memory (GUIConf.c)
uC/GUI needs a heap arena for windows, objects, fonts, etc.
-
Increase
GUI_NUMBYTESfor complex UIs, antialiased fonts, or multiple layers.
3) Choose the right display driver (LCDConf.c)
uC/GUI talks to your panel via a driver. Two common families:
A) RGB panels via LTDC (F429/F746/H7…)
-
Use
GUIDRV_Linwith color conversion likeGUICC_M565(RGB565) orGUICC_M8888I(ARGB8888). -
Enable LTDC and DMA2D in CubeMX; set timings to your panel.
-
Example:
-
Hook VSYNC/line interrupt to
GUI_MULTIBUF_Confirm()if you do true multibuffering.
B) SPI-attached controllers (ILI9341/ST7789/GC9A01…)
-
Use
GUIDRV_FlexColorwith the proper controller modes. -
You implement low-level read/write funcs (cmd/data) that call your SPI (preferably with DMA).
-
Example sketch:
Adjust controller variant and mode to your panel; init sequence (sleep-out, pixel format, MADCTL) belongs in your LCD init driver before GUI starts.
4) OS interface & timing (GUI_X.c)
-
Bare-metal: provide
GUI_X_GetTime()(millis) andGUI_X_Delay(ms)using SysTick. -
With RTOS (FreeRTOS/uC/OS-II): implement mutex/lock wrappers so emWin can be called from different tasks; call
GUI_Delay()or run a GUI task.
Bare-metal skeleton:
FreeRTOS idea:
5) Initialize in main()
-
Bring up clocks, GPIO, SPI/LTDC, DMA, touch, etc.
-
Init GUI last, after display/touch are ready.
6) Touch input (optional)
-
For resistive: read ADC X/Y, feed to emWin via
GUI_TOUCH_StoreStateEx(&State). -
For capacitive (FT6206/GT911 via I²C): read coordinates/press state periodically or in IRQ, then:
-
Run
GUI_TOUCH_Calibrate()or map raw → screen coordinates.
7) Fonts, languages, AA
-
Include the fonts you need (ASCII/Unicode). Antialiasing needs more GUI_NUMBYTES.
-
For Chinese or mixed locales, consider SIF/TTF support and external font caches.
8) Performance tips
-
LTDC/DMA2D: enable and let emWin use it for fills/blits; huge speedup.
-
SPI panels: use DMA + largest possible bursts; keep command/data switches minimal; consider parallel 8080 if bandwidth is tight.
-
Caches (F7/H7): if framebuffer in D-Cacheable SRAM/SDRAM, do cache maintenance (clean/invalidate) or mark region non-cacheable (MPU).
-
Use multiple buffers (double/triple) to avoid tearing; sync to VSYNC/line event.
9) Common pitfalls (quick fix list)
-
Wrong color order (BGR vs RGB) → scrambled colors → fix MADCTL / color conversion (
GUICC_M565vsGUICC_565). -
Forgetting
GUI_Exec()/GUI_Delay()in the main/GUI task → widgets don’t update. -
Too small
GUI_NUMBYTES→ random GUI alloc failures; increase pool size. -
SPI too slow for full-screen redraw → enable DMA, partial redraws, or use LTDC panels.
-
Touch coords swapped/inverted → unify with transform or correct controller settings.
-
Interrupt priorities vs. HAL DMA callbacks causing artifacts → review NVIC priorities for LCD/Touch/DMA2D.
10) Minimal “it works” checklist
-
Panel initializes (backlight on, test pattern OK).
-
GUI_Init()returns;GUI_DispString()shows text at expected position. -
Touch events move a demo widget (e.g.,
GUIDEMO_Start()if available). -
No tearing/flicker during simple animations.

评论
发表评论