2. 开发环境搭建:硬件平台选择、LVGL源码获取、RTOS移植、工程模板创建

好,咱们正式开始动手了。

这一章,说白了就是「把家伙事儿备齐」。很多初学者一上来就急着写代码,结果编译报错、跑不起来,折腾半天发现是环境没搭对。我当年也吃过这个亏,所以今天咱们一步到位,把硬件、源码、RTOS、工程模板全捋清楚。

2.1 硬件平台怎么选?

做LVGL+RTOS的项目,硬件选型其实有套路。我个人习惯看三点:RAM够不够、Flash够不够、屏驱好不好接

LVGL本身对RAM要求不高,但你要是开双缓冲、开动画,那内存就得往上走。我建议至少256KB RAM + 2MB Flash起步。

下面是我常用的几款平台,供你参考:

芯片/开发板 RAM Flash 屏驱接口 我的评价
ESP32-S3 512KB 16MB SPI / RGB 性价比之王,WiFi蓝牙都有
STM32F429 256KB 2MB LTDC / FMC 老牌劲旅,资料多
STM32H743 1MB 2MB LTDC / RGB 性能猛,适合复杂界面
NXP RT1064 1MB 4MB eLCDIF / RGB 跑LVGL丝滑,就是贵点
我的建议: 如果你是新手,先拿ESP32-S3练手。便宜、好买、社区活跃。我在项目里踩过的坑,基本都能在论坛上找到答案。

2.2 LVGL源码怎么拿?

LVGL的源码获取,其实就两条路:GitHub直接拉,或者用官方提供的包管理器

我个人更推荐直接拉GitHub,因为你能看到最新的commit,还能切分支。你想想看,万一你用的版本有bug,最新版可能已经修了。

操作很简单:

git clone https://github.com/lvgl/lvgl.git
cd lvgl
git checkout v8.3.0  # 选一个稳定版本

嗯,这里要注意:别用master分支。master是开发分支,可能今天能编译,明天就报错。我建议用v8.3.xv9.0.x,这两个版本比较稳。

拿到源码后,目录结构是这样的:

  • lvgl/src — 核心源码,别乱动
  • lvgl/examples — 官方示例,参考价值很大
  • lvgl/demos — 演示项目,可以跑起来看看效果
  • lvgl/lv_conf_template.h — 配置文件模板,这个要复制出来改
避坑指南: 我曾经直接把lv_conf_template.h放在原目录下改,结果一更新源码就被覆盖了。正确做法是:复制到你的工程目录下,重命名为lv_conf.h

2.3 RTOS怎么移植?

RTOS的选择,我建议用FreeRTOS。为什么?因为LVGL官方就推荐它,而且市面上大部分MCU都支持。说白了,你学一个,到处都能用。

移植RTOS,核心就三步:

  1. 下载FreeRTOS源码 — 从GitHub或官方包拿
  2. 配置系统时钟和中断 — 这个跟芯片相关,得看手册
  3. 创建任务 — 至少一个任务跑LVGL,一个任务跑业务逻辑

我贴一个最简的FreeRTOS任务创建代码,你感受一下:

#include "FreeRTOS.h"
#include "task.h"

void lvgl_task(void *pvParameters) {
    while(1) {
        lv_task_handler();  // LVGL的心跳
        vTaskDelay(pdMS_TO_TICKS(5));  // 每5ms跑一次
    }
}

void app_task(void *pvParameters) {
    while(1) {
        // 你的业务逻辑
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

int main(void) {
    // 硬件初始化...
    lv_init();

    xTaskCreate(lvgl_task, "LVGL", 4096, NULL, 2, NULL);
    xTaskCreate(app_task, "APP", 4096, NULL, 1, NULL);

    vTaskStartScheduler();
    while(1);
}
一个小技巧: LVGL任务优先级设高一点(比如2),业务任务设低一点(比如1)。这样界面响应快,用户体验好。我在做智能家居面板时就是这么干的,触摸滑动一点不卡。

2.4 工程模板怎么创建?

这一步,我建议你别从零开始。你想想看,每次新建项目都要配一堆路径、加一堆文件,多烦?

我的做法是:做一个通用模板,以后直接复制改

模板目录结构长这样:

my_lvgl_project/
├── src/
│   ├── main.c
│   ├── lvgl_port/
│   │   ├── lv_port_disp.c   // 显示驱动
│   │   ├── lv_port_indev.c  // 输入设备驱动
│   │   └── lv_port_fs.c     // 文件系统(可选)
│   └── app/
│       └── ui_screen.c      // 你的界面代码
├── lvgl/                    // LVGL源码
├── FreeRTOS/                // RTOS源码
├── drivers/                 // 芯片外设驱动
├── lv_conf.h                // LVGL配置
└── Makefile / .ioc          // 构建文件

这里最关键的是lv_port_disp.clv_port_indev.c。这两个文件是LVGL和硬件的桥梁。你只要把显示驱动和触摸驱动填进去,LVGL就能跑起来。

我贴一个最简的显示驱动初始化:

static lv_disp_drv_t disp_drv;
static lv_color_t buf[LV_HOR_RES_MAX * 10];  // 缓冲区

void lv_port_disp_init(void) {
    lv_disp_drv_init(&disp_drv);
    disp_drv.flush_cb = my_disp_flush;  // 你的刷屏函数
    disp_drv.buffer = lv_disp_draw_buf_init(&buf, NULL, LV_HOR_RES_MAX * 10);
    lv_disp_drv_register(&disp_drv);
}

void my_disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) {
    // 把color_p的数据刷到屏幕的area区域
    // 刷完后调用 lv_disp_flush_ready(drv);
}
注意: 缓冲区大小别设太小。我见过有人设成LV_HOR_RES_MAX * 1,结果刷屏慢得像PPT。建议至少10行的缓冲区。

2.5 验证一下:跑个Hello World

模板建好后,咱们跑个最简单的例子,验证环境对不对:

void ui_create(void) {
    lv_obj_t *label = lv_label_create(lv_scr_act());
    lv_label_set_text(label, "Hello, LVGL + FreeRTOS!");
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}

int main(void) {
    // 硬件初始化
    // RTOS初始化
    // LVGL初始化
    // 显示驱动初始化

    ui_create();

    vTaskStartScheduler();
    while(1);
}

如果屏幕上出现了「Hello, LVGL + FreeRTOS!」,恭喜你,环境搭好了!

嗯,到这里,开发环境就全齐了。下一章咱们开始真正写界面,到时候我会教你如何用LVGL的控件搭出一个完整的仪表盘。

本章小结:
  • 硬件选型看RAM和Flash,ESP32-S3是入门首选
  • LVGL源码从GitHub拉,用稳定版本
  • FreeRTOS移植三步走:下载、配置、建任务
  • 工程模板一次建好,以后复制改
  • 跑通Hello World,验证环境