嵌入式 GUI 开发指南:LVGL、GuiLite 实战

嵌入式 GUI 开发正在从简单的字符界面走向丰富的图形界面。本文介绍 GitHub 上最流行的嵌入式 GUI 框架,帮助你为 MCU 项目添加漂亮的用户界面。

一、主流嵌入式 GUI 框架

1. LVGL(Light and Versatile Graphics Library)

⭐ 22.8k Stars 最流行 C 语言

github.com/lvgl/lvgl

嵌入式 GUI 的事实标准,支持 MCU 到 Linux 平台,丰富控件和主题:

// LVGL 初始化示例(STM32 + ILI9341 屏幕)
#include "lvgl.h"

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf1[LV_HOR_RES_MAX * 10];
static lv_color_t buf2[LV_HOR_RES_MAX * 10];

void lvgl_init(void) {
    lv_init();
    lv_disp_draw_buf_init(&draw_buf, buf1, buf2, LV_HOR_RES_MAX * 10);
    
    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf = &draw_buf;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.hor_res = 320;
    disp_drv.ver_res = 240;
    lv_disp_drv_register(&disp_drv);
}

// 创建一个简单的 UI
void create_ui(void) {
    lv_obj_t *scr = lv_scr_act();
    
    // 标题
    lv_obj_t *title = lv_label_create(scr);
    lv_label_set_text(title, "IoT Monitor");
    lv_obj_set_style_text_font(title, &lv_font_montserrat_24, 0);
    lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10);
    
    // 温度显示
    lv_obj_t *temp_label = lv_label_create(scr);
    lv_label_set_text(temp_label, "25.5°C");
    lv_obj_set_style_text_font(temp_label, &lv_font_montserrat_48, 0);
    lv_obj_set_style_text_color(temp_label, lv_color_hex(0x00FF00), 0);
    lv_obj_align(temp_label, LV_ALIGN_CENTER, 0, 0);
    
    // 图表
    lv_obj_t *chart = lv_chart_create(scr);
    lv_obj_set_size(chart, 300, 100);
    lv_obj_align(chart, LV_ALIGN_BOTTOM_MID, 0, -10);
    lv_chart_set_type(chart, LV_CHART_TYPE_LINE);
    lv_chart_set_point_count(chart, 20);
}
推荐

TFT 显示屏 - GUI 项目必备

2.8 寸 ILI9341 TFT 触摸屏,320x240 分辨率,SPI 接口,适合 LVGL 项目。

查看 Amazon 价格 →

2. GuiLite

⭐ 7.7k Stars 超轻量 4KB RAM

github.com/aspect-tech/GuiLite

仅 4KB 代码的超轻量 GUI 库,适合资源受限的 MCU:

// GuiLite 最小示例
#include <guilite.h>

// 按钮回调
void on_button_click(void) {
    static bool led_state = false;
    led_state = !led_state;
    led_control(led_state);
}

// 创建界面
void create_ui() {
    // 创建按钮
    button_t *btn = new button_t(10, 100, 200, 50, "Toggle LED");
    btn->set_on_click_handler(on_button_click);
    
    // 创建标签
    label_t *lbl = new label_t(10, 10, "Hello GuiLite!");
    lbl->set_font_size(24);
    lbl->set_text_color(0x00FF00);
}

3. emWin(SEGGER)

商业 工业级 NXP/ST

工业级 GUI 库,NXP 和 ST 的 MCU 可免费使用:

  • 支持抗锯齿字体、动画、窗口管理器
  • 丰富的控件库(按钮、列表、图表等)
  • 支持触摸屏、鼠标、键盘输入
  • 配套 GUIBuilder 可视化设计工具

4. TouchGFX(ST)

免费 STM32 专用 高帧率

ST 官方的 GUI 框架,针对 STM32 + Chrom-ART 加速优化:

  • 支持 60fps 流畅动画
  • TouchGFX Designer 可视化设计
  • 自动生成 C++ 代码
  • 免费用于 STM32 芯片

二、GUI 开发硬件选型

MCU RAM 适合框架 参考价格
STM32F407 192KB LVGL、TouchGFX $15
STM32F746 320KB TouchGFX、LVGL $25
ESP32-S3 512KB LVGL、GuiLite $12
NXP RT1062 1MB emWin、LVGL $30

三、LVGL 实战项目

智能家居仪表盘

// LVGL 智能家居仪表盘
void create_smart_home_ui(void) {
    lv_obj_t *scr = lv_scr_act();
    
    // 顶部状态栏
    lv_obj_t *status_bar = lv_obj_create(scr);
    lv_obj_set_size(status_bar, LV_PCT(100), 40);
    lv_obj_align(status_bar, LV_ALIGN_TOP_MID, 0, 0);
    
    lv_obj_t *wifi_icon = lv_label_create(status_bar);
    lv_label_set_text(wifi_icon, LV_SYMBOL_WIFI);
    lv_obj_align(wifi_icon, LV_ALIGN_LEFT_MID, 10, 0);
    
    lv_obj_t *time_label = lv_label_create(status_bar);
    lv_label_set_text(time_label, "14:30");
    lv_obj_align(time_label, LV_ALIGN_RIGHT_MID, -10, 0);
    
    // 温度卡片
    lv_obj_t *temp_card = lv_obj_create(scr);
    lv_obj_set_size(temp_card, 140, 100);
    lv_obj_align(temp_card, LV_ALIGN_TOP_LEFT, 10, 50);
    
    lv_obj_t *temp_icon = lv_label_create(temp_card);
    lv_label_set_text(temp_icon, LV_SYMBOL_HEAT);
    lv_obj_set_style_text_color(temp_icon, lv_color_hex(0xFF6B6B), 0);
    lv_obj_align(temp_icon, LV_ALIGN_TOP_LEFT, 5, 5);
    
    lv_obj_t *temp_value = lv_label_create(temp_card);
    lv_label_set_text(temp_value, "25.5°C");
    lv_obj_set_style_text_font(temp_value, &lv_font_montserrat_24, 0);
    lv_obj_align(temp_value, LV_ALIGN_BOTTOM_LEFT, 5, -5);
    
    // 湿度卡片
    lv_obj_t *hum_card = lv_obj_create(scr);
    lv_obj_set_size(hum_card, 140, 100);
    lv_obj_align(hum_card, LV_ALIGN_TOP_RIGHT, -10, 50);
    
    lv_obj_t *hum_icon = lv_label_create(hum_card);
    lv_label_set_text(hum_icon, LV_SYMBOL_DROPLET);
    lv_obj_set_style_text_color(hum_icon, lv_color_hex(0x4ECDC4), 0);
    lv_obj_align(hum_icon, LV_ALIGN_TOP_LEFT, 5, 5);
    
    lv_obj_t *hum_value = lv_label_create(hum_card);
    lv_label_set_text(hum_value, "60%");
    lv_obj_set_style_text_font(hum_value, &lv_font_montserrat_24, 0);
    lv_obj_align(hum_value, LV_ALIGN_BOTTOM_LEFT, 5, -5);
    
    // LED 控制开关
    lv_obj_t *led_switch = lv_switch_create(scr);
    lv_obj_align(led_switch, LV_ALIGN_BOTTOM_MID, 0, -50);
    lv_obj_add_event_cb(led_switch, led_switch_handler, LV_EVENT_VALUE_CHANGED, NULL);
}

四、GUI 开发最佳实践

  • 内存管理:MCU RAM 有限,使用对象池避免频繁 malloc
  • 刷新策略:只刷新变化的区域,减少 GPU 负载
  • 字体选择:使用内置字体,避免加载外部字体占用 Flash
  • 输入处理:触摸屏需要校准和去抖动处理
  • 多语言支持:使用 Unicode 字符集支持中英文
嵌入式 GUI 开发的关键是在美观和资源消耗之间找到平衡。
← 返回首页