Skip to content

概念先知道

  • LVGL v8:LVGL 图形库的成熟稳定版本,控件与绘图 API 与 v9 大同小异,但部分接口不同(详见 FAQ)。
  • tick 驱动方式差异:v8 例程没有显式设置 tick 回调(由 lv_port_disp_init 内部用 lv_tick_inc 驱动),v9 则用 lv_tick_set_cb 注册回调。
  • 显示驱动:同样通过 lv_port_disp_init 初始化 LCD,屏幕型号/引脚在 lcd_conf_user.h 中配置。
  • 演示切换:默认跑 benchmark,注释里提供了 widgets、music、stress 等演示,取消注释即可切换。

例程功能简介

本页对应博流官方 SDK 的 lvgl_v8 例程(examples/lvgl/lvgl_v8),演示 LVGL v8 在 Ai-M6x 上运行:

  • 注册日志回调(lv_log_register_print_cb),初始化 LVGL 核心(lv_init);
  • lv_port_disp_init 初始化 LCD 显示驱动;
  • 运行 benchmark 演示lv_demo_benchmark);其他演示以注释形式列出;
  • 主循环周期调用 lv_task_handler() 刷新画面。
  • 同族例程examples/lvgl/):lvgl_v9(v9 版本)、lvgl_v8_with_osd / lvgl_v9_with_osd(带 OSD 图层版本)。

注意

LVGL 例程依赖 LCD 显示屏与对应驱动。不同开发板屏幕型号、引脚和分辨率不同,需要按板子的 lcd_conf_user.h 配置核对;没有接屏的板子无法看到画面。

操作步骤

1
进入例程目录

本页需要一块带屏幕的开发板。在终端进入 SDK 的 LVGL v8 例程目录(前提:已按快速开始(Linux)Windows搭建好环境):

cd examples/lvgl/lvgl_v8
2
编译工程

执行编译命令。Ai-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写引脚最少的 bl616 即可:

make CHIP=bl616 BOARD=bl616dk
3
烧录固件

用 USB 线连接开发板,按住 BOOT 键(Ai-M61-32S-Kit 为 IO2)不放、短按 EN/RST 进入下载模式,然后执行烧录(把串口号换成实际值):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
4
运行验证

打开串口助手(波特率 2000000)。程序打印 LVGL V8 case 和版本号后,屏幕运行 benchmark 性能演示,串口打印 lvgl success

代码执行流程

例程从启动到画面刷新的完整流程如下(图中的循环箭头表示反复执行):

例程调用的 API 介绍

lv_log_register_print_cb(cb)

注册 LVGL 日志输出回调,把 LVGL 内部日志转到串口。

参数

  • cb:日志回调函数(例程为 lv_log_print_g_cb

返回值:无

lv_init()

初始化 LVGL 核心库,必须在任何其他 LVGL API 之前调用。

参数:无

返回值:无

lv_port_disp_init()

初始化 LVGL 显示端口(LCD 驱动),并注册 tick 递增(lv_tick_inc)。

参数:无

返回值:无

lv_demo_benchmark()

启动 benchmark 演示,绘制各类图形并统计渲染性能。其他演示(lv_demo_widgetslv_demo_musiclv_demo_stress 等)取消注释即可切换。

参数:无

返回值:无

lv_task_handler()

LVGL 任务处理函数:推进动画并刷新显示,必须在主循环中周期调用。

参数:无

返回值:无

完整代码

以下为 lvgl_v8/main.c 完整源码,与官方示例(examples/lvgl/lvgl_v8)一致,默认折叠,点击展开:

📜 点击展开 lvgl_v8/main.c 完整代码
c
/**
 * @file main.c
 * @brief
 *
 * Copyright (c) 2021 Bouffalolab team
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 *
 */
#include "board.h"
#include "bflb_gpio.h"
#include "bflb_l1c.h"
#include "bflb_mtimer.h"

#include "lcd.h"

#if defined(CONFIG_FREERTOS)
#include <FreeRTOS.h>
#include "task.h"
#endif

#include "lvgl.h"
#include "lv_port_disp.h"
#ifdef CONFIG_LVGL8_PORT_INDEV
#include "lv_port_indev.h"
#endif

#include "demos/lv_demos.h"

#define DBG_TAG "MAIN"
#include "log.h"

#if defined(CONFIG_FREERTOS)
static TaskHandle_t lvgl_handle;
#endif

/* lvgl log cb */
void lv_log_print_g_cb(const char *buf)
{
    LOG_RI("[LVGL]%s", buf);
}

void lvgl_main(void *param)
{
    /* lvgl init */
    lv_log_register_print_cb(lv_log_print_g_cb);
    lv_init();
    lv_port_disp_init();
#ifdef CONFIG_LVGL8_PORT_INDEV
    lv_port_indev_init();
#endif
    // lv_disp_set_rotation(NULL, LV_DISP_ROT_90);

    lv_demo_benchmark();
    // lv_demo_keypad_encoder();
    // lv_demo_music();
    // lv_demo_stress();
    // lv_demo_widgets();

    lv_task_handler();

    LOG_I("lvgl success\r\n");

    while (1) {
        lv_task_handler();
        bflb_mtimer_delay_us(10);
    }
}

int main(void)
{
    board_init();

    LOG_I("LVGL V8 case\r\n");
    LOG_I("LVGL VER: %d.%d.%d\r\n", LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, LVGL_VERSION_PATCH);

#if defined(CONFIG_FREERTOS)
    xTaskCreate(lvgl_main, (char *)"test_task", 2048, NULL, configMAX_PRIORITIES - 2, &lvgl_handle);
    vTaskStartScheduler();
#else
    lvgl_main(NULL);
#endif
}

FAQ

v8 和 v9 怎么选

新项目建议直接用 v9(LVGL v9 图形界面);如果项目已有 v8 代码或依赖旧组件,用 v8。两者 SDK 例程均可直接编译运行。

tick 是怎么驱动的

v8 例程由 lv_port_disp_init 内部按 lv_tick_inc 递增 tick;v9 例程显式调用 lv_tick_set_cb。手写工程时记得保证 tick 持续递增,否则动画和刷新会卡住。

屏幕没有画面

确认开发板接了 LCD 屏,且 lcd_conf_user.h 的屏幕型号、分辨率、引脚与板子一致;再确认 lv_port_disp_init 正常执行(可看串口是否有 LVGL 日志)。

遇到问题?

如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23