第二章 开发环境搭建:LVGL源码获取、模拟器环境搭建与硬件移植准备

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

上一章聊了LVGL能做什么,这一章咱们得把“家伙事儿”备齐。说白了,就是让LVGL能在你的电脑上跑起来,顺便看看怎么把它塞进真正的硬件里。

我个人习惯,学一个新东西,先别急着买开发板。先在PC上跑模拟器,省钱又省心。等逻辑调通了,再往板子上烧,效率高得多。

2.1 获取LVGL源码

源码去哪拿?GitHub。这个不用我多说了吧。

我建议你直接克隆官方仓库,别去下载那些乱七八糟的第三方打包版本。为什么?因为官方仓库更新最快,issue也最活跃,遇到问题好查。

git clone https://github.com/lvgl/lvgl.git
cd lvgl
git checkout v8.3.0  # 我个人习惯用稳定版,v8.3是目前比较稳的

嗯,这里要注意:LVGL现在有v9版本了,但很多第三方库和教程还是基于v8的。如果你刚入门,我建议先用v8,资料多,坑少。

除了核心库,你还需要一个“依赖包”——lv_drivers和lv_examples。不过现在官方推荐用lv_port_pc_eclipse或者lv_port_linux这种现成的移植工程。说白了,就是人家帮你搭好了架子,你直接往里面填代码就行。

我的小技巧: 如果你网络不好,可以去gitee上找镜像。但记得,镜像可能滞后几个版本。我遇到过镜像里缺了某个关键修复,折腾了半天才发现。

2.2 PC模拟器环境搭建

模拟器,说白了就是在你的Windows/Mac/Linux上跑一个LVGL的窗口。我推荐用SDL2或者Eclipse + SDL2的方案。

为什么选SDL2?因为它跨平台,而且LVGL官方对SDL2的支持最好。你想想看,如果选了个冷门的图形库,到时候出问题了连问的人都没有。

2.2.1 Windows下的SDL2模拟器

步骤其实很简单:

  1. 下载SDL2开发库(去libsdl.org下载Development Libraries)
  2. 创建一个新的C语言工程,把lvgl源码和lv_drivers源码加进去
  3. 配置包含路径和链接库
  4. 写一个main.c,初始化LVGL和SDL2

我直接给你一个最小化的main.c模板:

#include "lvgl.h"
#include "lv_drivers/display/monitor.h"
#include "lv_drivers/indev/mouse.h"

int main(void)
{
    lv_init();
    monitor_init();
    mouse_init();

    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.flush_cb = monitor_flush;
    lv_disp_drv_register(&disp_drv);

    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = mouse_read;
    lv_indev_drv_register(&indev_drv);

    // 创建一个简单的按钮测试
    lv_obj_t *btn = lv_btn_create(lv_scr_act());
    lv_obj_set_pos(btn, 100, 100);
    lv_obj_set_size(btn, 100, 50);

    while(1) {
        lv_task_handler();
        SDL_Delay(5);
    }

    return 0;
}

这段代码,说白了就是告诉LVGL:“嘿,你的显示输出走SDL2窗口,你的触摸输入走鼠标。” 跑起来之后,你会看到一个窗口,里面有个按钮。

避坑指南: 我曾经在Windows上折腾了一下午,发现SDL2的库版本不对。32位工程要用32位的SDL2库,64位工程要用64位的。混着用,链接阶段直接报错,而且错误信息特别隐晦。

2.2.2 Linux下的模拟器

Linux下更简单。你只需要装个SDL2开发包:

sudo apt-get install libsdl2-dev

然后编译的时候链接上SDL2就行。我个人习惯用CMake来管理工程,省事。

这里有个小细节:Linux下的显示刷新率默认是60fps,但LVGL的默认刷新率可能更高。你可以在lv_conf.h里调整:

#define LV_DISP_DEF_REFR_PERIOD 30  // 单位是毫秒,30ms约等于33fps

为什么要调?因为模拟器跑太快了,CPU占用高,风扇呼呼转。调低一点,开发体验更好。

2.3 硬件平台移植准备

模拟器跑通了,接下来就是真刀真枪上硬件了。

硬件移植,说白了就是三件事:

  • 显示驱动:告诉LVGL怎么往屏幕上画点
  • 触摸驱动:告诉LVGL触摸屏按在了哪里
  • 系统时钟:告诉LVGL时间过去了多久

我以STM32为例,给你讲讲移植的套路。

2.3.1 显示驱动接口

LVGL需要你实现一个“flush_cb”函数。这个函数的作用是:把LVGL画好的一块缓冲区,刷到屏幕上。

static void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    // 假设你用的是ILI9341屏幕
    ili9341_draw_bitmap(area->x1, area->y1, area->x2, area->y2, color_p);

    // 通知LVGL刷新完成
    lv_disp_flush_ready(disp_drv);
}

嗯,这里要注意:lv_disp_flush_ready一定要调用,否则LVGL会一直等着,界面卡死。

2.3.2 触摸驱动接口

触摸驱动更简单,实现一个“read_cb”函数:

static void my_touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    static int16_t last_x, last_y;
    static bool last_pressed;

    // 读取触摸芯片(比如FT6206)
    ft6206_read(&last_x, &last_y, &last_pressed);

    data->point.x = last_x;
    data->point.y = last_y;
    data->state = last_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
}

我曾经在一个项目里,触摸坐标死活不对。后来发现是触摸芯片的X轴和屏幕的X轴方向反了。解决办法很简单:在read_cb里把x和y互换一下,或者取个反。

2.3.3 系统时钟与心跳

LVGL需要一个“心跳”来驱动动画和任务调度。通常用一个硬件定时器,每1ms产生一次中断:

void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        lv_tick_inc(1);  // 告诉LVGL过去了1ms
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

然后在主循环里调用lv_task_handler()

while(1)
{
    lv_task_handler();
    delay_ms(5);
}
重要提醒: 不要在中断里调用lv_task_handler!中断服务程序应该尽量短。lv_tick_inc可以在中断里调用,但lv_task_handler必须在主循环里调用。

2.4 移植前的准备工作清单

在你开始移植之前,我建议你先确认以下几点:

项目 要求 我的建议
MCU主频 至少72MHz 最好100MHz以上,否则动画会卡
RAM大小 至少16KB 建议32KB以上,LVGL的缓冲区需要占用不少内存
Flash大小 至少128KB 如果用了中文字体,Flash需求会翻倍
显示接口 SPI/8080并口/RGB接口 SPI最常用,但刷新率低;RGB接口快,但引脚多

你想想看,如果MCU主频只有48MHz,RAM只有8KB,跑LVGL基本是自讨苦吃。我见过有人硬要在STM32F030上跑LVGL,结果界面卡成PPT,最后只能放弃。

2.5 本章小结

这一章,咱们把开发环境搭起来了。你在PC上跑通了模拟器,也知道了怎么往硬件上移植。说白了,就是“先模拟,后实机”。

下一章,咱们开始真正玩控件。从按钮开始,一步步搭出漂亮的界面。

嗯,如果你在搭建环境时遇到问题,别急。LVGL的社区很活跃,GitHub的issue里基本能找到答案。实在不行,去论坛发帖,记得附上你的代码和错误信息。

我的经验: 移植过程中,90%的问题出在显示驱动上。如果你发现屏幕不亮或者花屏,先检查SPI时序和初始化序列。我曾经花了两天时间,最后发现是屏幕的复位引脚没拉高。

好了,动手吧。把模拟器跑起来,感受一下LVGL的魅力。