第二章 开发环境搭建:硬件平台选择与第一个LVGL工程

好,咱们正式开始动手了。这一章我带你走一遍开发环境的搭建流程。说实话,很多初学者卡在这一步就放弃了——工具链装不上、源码编译报错、下载器不识别……我当年也踩过不少坑。今天我把经验都摊开讲,你跟着走就行。

2.1 硬件平台怎么选?STM32还是ESP32?

这个问题我几乎每次线下课都会被问到。我的回答是:看你最终产品要什么

先看一张对比表,心里有个底:

对比项 STM32(以F4/H7为例) ESP32(以ESP32-S3为例)
主频 168~480 MHz 240 MHz
RAM 192KB~1MB(片内) 512KB(片内)+ 8MB PSRAM
Flash 1~2MB(片内) 16MB(外挂)
LVGL流畅度 中等(需优化显存) 流畅(PSRAM加持)
WiFi/蓝牙 需外挂模块 内置
开发成本 中等(板子+调试器) 低(USB下载即可)
适合场景 工业控制、医疗设备 智能家居、物联网屏显

我个人习惯是:学LVGL入门用ESP32。为什么?因为ESP32有PSRAM,你不用担心内存不够用。我刚开始用STM32F103跑LVGL时,一个简单的仪表盘界面就把内存撑爆了,折腾了两天才搞定显存分配。ESP32就没这烦恼,8MB PSRAM随便用。

但如果你做的是工业产品,对稳定性要求极高,那还是STM32更靠谱。ESP32的WiFi射频有时候会干扰屏显刷新,我在一个智能家居项目里遇到过这个问题,后来加了屏蔽罩才解决。

我的建议: 初学者先用ESP32-S3开发板(比如合宙的C3或者乐鑫的官方板),成本不到50块。等把LVGL玩熟了,再移植到STM32上做产品。

2.2 软件工具链安装

工具链这东西,说白了就是「编译器+调试器+烧录工具」的组合。不同平台用的工具不一样,我分开讲。

2.2.1 ESP32开发环境

我推荐用ESP-IDF,别用Arduino。虽然Arduino上手快,但LVGL在ESP-IDF下性能更好,而且内存管理更灵活。

安装步骤:

  1. 安装Python 3.8+ —— 记得勾选「Add Python to PATH」
  2. 安装Git —— 后面拉取LVGL源码要用
  3. 安装ESP-IDF —— 打开终端,运行:
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh  # Windows用 install.bat
. ./export.sh  # Windows用 export.bat

嗯,这里要注意:install.sh会下载编译工具链,大概1~2GB,网速慢的话可能要等半小时。我建议你找个有梯子的网络环境,或者用国内镜像。

我曾经踩过的坑: 第一次安装时忘了加 --recursive 参数,结果子模块没拉全,编译时疯狂报错。后来我学乖了,每次都用 git clone --recursive

2.2.2 STM32开发环境

STM32这边,我习惯用STM32CubeIDE。它集成了GCC编译器、调试器和CubeMX配置工具,一套搞定。

安装流程:

  • 去ST官网下载STM32CubeIDE(需要注册账号)
  • 安装时选择「Full Installation」,大概1.5GB
  • 安装完成后,打开CubeMX,配置一个工程试试

如果你喜欢用Keil或者IAR,也行。但我个人觉得CubeIDE免费又好用,没必要花几万块买Keil授权。

2.3 LVGL源码获取与移植

LVGL的源码托管在GitHub上。获取方式很简单:

git clone https://github.com/lvgl/lvgl.git
cd lvgl
git checkout v8.3.0  # 建议用稳定版

为什么我推荐v8.3.0?因为v9.0改动太大,很多API都变了,网上教程大多基于v8。等v9稳定了再升级也不迟。

移植LVGL到你的工程,核心就三步:

  1. 复制源码 —— 把 lvgl 文件夹放到你的工程目录下
  2. 配置lv_conf.h —— 这是LVGL的配置文件,里面可以开关功能、调整内存大小
  3. 实现三个接口 —— 显示驱动、触摸驱动、系统时钟

我重点说一下 lv_conf.h 的配置。你打开这个文件,找到这几项:

#define LV_COLOR_DEPTH     16    // 颜色深度,16位够用
#define LV_MEM_SIZE        (64U * 1024U)  // LVGL动态内存,64KB起步
#define LV_HOR_RES_MAX     320   // 屏幕宽度
#define LV_VER_RES_MAX     240   // 屏幕高度
#define LV_USE_DEMO_WIDGETS 1    // 打开示例,方便测试

关键点: LV_MEM_SIZE 不要设太小。我见过有人设成8KB,结果界面稍微复杂一点就卡死。ESP32有PSRAM,可以设到256KB甚至更大。STM32如果片内RAM紧张,设64KB也够用。

2.4 第一个LVGL工程

好了,环境搭好了,源码也放进去了。咱们来跑第一个程序。

以ESP32为例,在 main.c 里写:

#include "lvgl.h"
#include "lv_examples.h"

void app_main(void)
{
    // 1. 初始化LVGL
    lv_init();

    // 2. 初始化显示驱动(这里用你的屏幕驱动函数)
    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.flush_cb = my_disp_flush;  // 你的刷屏函数
    disp_drv.hor_res = 320;
    disp_drv.ver_res = 240;
    lv_disp_drv_register(&disp_drv);

    // 3. 初始化触摸驱动(如果有触摸屏)
    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;  // 你的触摸读取函数
    lv_indev_drv_register(&indev_drv);

    // 4. 创建一个按钮
    lv_obj_t *btn = lv_btn_create(lv_scr_act());
    lv_obj_set_pos(btn, 100, 80);
    lv_obj_set_size(btn, 120, 50);

    lv_obj_t *label = lv_label_create(btn);
    lv_label_set_text(label, "Hello LVGL!");

    // 5. 主循环
    while(1) {
        lv_timer_handler();  // 处理LVGL任务
        vTaskDelay(5 / portTICK_PERIOD_MS);  // 延时5ms
    }
}

这段代码干了什么?说白了就是:初始化LVGL → 告诉它你的屏幕怎么刷 → 创建一个按钮 → 循环处理界面事件。

你编译烧录后,屏幕上应该会出现一个带「Hello LVGL!」文字的按钮。如果没显示,别慌,先检查这几个地方:

  • 屏幕的SPI/I2C引脚有没有接对?
  • my_disp_flush 函数里有没有调用 lv_disp_flush_ready()
  • lv_timer_handler() 有没有在主循环里被调用?

一个小技巧: 如果屏幕没显示,先别急着查硬件。在 my_disp_flush 里直接填充全屏红色,看看屏幕能不能亮。能亮说明硬件没问题,问题出在LVGL配置上。

我记得第一次跑通LVGL时,看到屏幕上那个按钮,心里还挺激动的。虽然只是个简单的按钮,但意味着你的嵌入式设备有了「图形界面」的能力。后面咱们会一步步把它做成完整的仪表盘、智能家居面板……

好,这一章就到这儿。环境搭好了,第一个工程也跑起来了。下一章咱们开始深入LVGL的组件系统,看看那些按钮、标签、滑块到底怎么用。


公众号:蓝海资料掘金营,微信deep3321