你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32U3 评测】Zephyr超简单的移植lvgl

[复制链接]
lugl 发布时间:2026-5-28 21:44

【前言】

在前一篇我使用zephyr来驱动了st7789LCD屏,只需要添加少量代码就可以实现lvgl。

【实现步骤】

1、prj.conf中添加宏开关:

    LVGL 核心
    CONFIG_LVGL=y
    CONFIG_LV_USE_LOG=y
    CONFIG_LV_USE_LABEL=y
    CONFIG_LV_USE_ARC=y
    CONFIG_LV_USE_BUTTON=y
    CONFIG_LV_USE_LINE=y
    CONFIG_LV_USE_IMAGE=y
    CONFIG_LV_FONT_MONTSERRAT_14=y

    显示缓冲区(静态分配)
    CONFIG_LV_Z_VDB_SIZE=25
    CONFIG_LV_Z_BUFFER_ALLOC_STATIC=y
    CONFIG_LV_Z_DOUBLE_VDB=y
    CONFIG_LV_Z_VDB_ALIGN=4
    CONFIG_LV_COLOR_DEPTH_16=y
    CONFIG_LV_Z_BITS_PER_PIXEL=16

    LVGL 运行时
    CONFIG_LV_Z_MEM_POOL_SIZE=16384
    CONFIG_LV_Z_INIT_PRIORITY=50
    CONFIG_LV_Z_LVGL_WORKQUEUE_STACK_SIZE=2048
    CONFIG_LV_Z_LVGL_WORKQUEUE_PRIORITY=10
    CONFIG_LV_Z_RUN_LVGL_ON_WORKQUEUE=n
    CONFIG_LV_Z_LVGL_MUTEX=y

2、添加main.c中的代码:

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/display.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/input/input.h>
#include <zephyr/kernel.h>
#include <lvgl.h>

#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(app);

/* BLK (backlight) on PE11 */
#define BLK_GPIO_NODE   DT_NODELABEL(gpioe)
#define BLK_PIN     11

static uint32_t counter;
static lv_obj_t *counter_label;
static const struct device *blk_gpio;
static int blink_state;

static void touch_cb(struct input_event *evt, void *user_data)
{
    if (evt->type == INPUT_EV_ABS) {
        if (evt->code == INPUT_ABS_X) {
            LOG_INF("touch X=%d", evt->value);
        } else if (evt->code == INPUT_ABS_Y) {
            LOG_INF("touch Y=%d", evt->value);
        }
    } else if (evt->type == INPUT_EV_KEY && evt->code == INPUT_BTN_TOUCH) {
        LOG_INF("touch %s", evt->value ? "PRESS" : "RELEASE");
    }
}
INPUT_CALLBACK_DEFINE(NULL, touch_cb, NULL);

static void btn_clear_cb(lv_event_t *e)
{
    counter = 0;
    lv_label_set_text_fmt(counter_label, "%u", counter);
}

static void btn_blk_cb(lv_event_t *e)
{
    blink_state = !blink_state;
    gpio_pin_set(blk_gpio, BLK_PIN, blink_state ? 1 : 0);
}

int main(void)
{
    const struct device *display_dev;
    int ret;

    LOG_INF("STM32U3C5 ST7789V LVGL demo");

    display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
    if (!device_is_ready(display_dev)) {
        LOG_ERR("Display device not ready");
        return 0;
    }

    blk_gpio = DEVICE_DT_GET(BLK_GPIO_NODE);
    if (!device_is_ready(blk_gpio)) {
        LOG_ERR("BLK GPIO not ready");
        return 0;
    }

    ret = gpio_pin_configure(blk_gpio, BLK_PIN, GPIO_OUTPUT_HIGH);
    if (ret < 0) {
        LOG_ERR("BLK pin config failed: %d", ret);
        return 0;
    }

    display_blanking_off(display_dev);

    /* UI */
    lv_obj_t *scr = lv_screen_active();
    lv_obj_set_style_bg_color(scr, lv_color_hex(0x111122), LV_PART_MAIN);

    /* Title label */
    lv_obj_t *title = lv_label_create(scr);
    lv_label_set_text(title, "STM32U3C5 + ST7789V");
    lv_obj_set_style_text_color(title, lv_color_hex(0x00FFFF), LV_PART_MAIN);
    lv_obj_set_style_text_font(title, &lv_font_montserrat_14, LV_PART_MAIN);
    lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 8);

    /* Arc progress bar */
    lv_obj_t *arc = lv_arc_create(scr);
    lv_obj_set_size(arc, 80, 80);
    lv_arc_set_rotation(arc, 135);
    lv_arc_set_bg_angles(arc, 0, 270);
    lv_arc_set_value(arc, 0);
    lv_obj_set_style_arc_color(arc, lv_color_hex(0x00FF00), LV_PART_MAIN);
    lv_obj_set_style_arc_color(arc, lv_color_hex(0xFF8800), LV_PART_INDICATOR);
    lv_obj_align(arc, LV_ALIGN_CENTER, 0, -20);

    /* Counter label */
    counter_label = lv_label_create(scr);
    lv_label_set_text_fmt(counter_label, "%u", counter);
    lv_obj_set_style_text_color(counter_label, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
    lv_obj_set_style_text_font(counter_label, &lv_font_montserrat_14, LV_PART_MAIN);
    lv_obj_align(counter_label, LV_ALIGN_CENTER, 0, 20);

    /* Hello button */
    lv_obj_t *btn_hello = lv_button_create(scr);
    lv_obj_set_size(btn_hello, 100, 32);
    lv_obj_align(btn_hello, LV_ALIGN_CENTER, 0, 60);
    lv_obj_add_event_cb(btn_hello, btn_clear_cb, LV_EVENT_CLICKED, NULL);
    lv_obj_t *lbl_hello = lv_label_create(btn_hello);
    lv_label_set_text(lbl_hello, "Clear Counter");
    lv_obj_set_style_text_color(lbl_hello, lv_color_hex(0xFFFFFF), LV_PART_MAIN);

    /* BLK toggle button */
    lv_obj_t *btn_blk = lv_button_create(scr);
    lv_obj_set_size(btn_blk, 100, 32);
    lv_obj_align(btn_blk, LV_ALIGN_CENTER, 0, 100);
    lv_obj_add_event_cb(btn_blk, btn_blk_cb, LV_EVENT_CLICKED, NULL);
    lv_obj_t *lbl_blk = lv_label_create(btn_blk);
    lv_label_set_text(lbl_blk, "Toggle BLK");
    lv_obj_set_style_text_color(lbl_blk, lv_color_hex(0xFFFF00), LV_PART_MAIN);

    /* Bottom hint */
    lv_obj_t *hint = lv_label_create(scr);
    lv_label_set_text(hint, "Zephyr + LVGL v9");
    lv_obj_set_style_text_color(hint, lv_color_hex(0x888888), LV_PART_MAIN);
    lv_obj_set_style_text_font(hint, &lv_font_montserrat_12, LV_PART_MAIN);
    lv_obj_align(hint, LV_ALIGN_BOTTOM_MID, 0, 8);

    while (1) {
        lv_timer_handler();
        k_sleep(K_MSEC(5));
        counter++;
        lv_label_set_text_fmt(counter_label, "%u", counter);
        lv_arc_set_value(arc, (counter / 10) % 100);
    }
}

编译后下载到开发板就可以实现lvgl的漂亮界面了:

2cfb9547-5fe3-4600-a2eb-9605a5f15415.png

【注意事项】

颜色问题:Zephyr SPI 8bit 模式按小端顺序发送像素,而裸机先发高字节再发低字节。需要在 display_st7789v.c 的 st7789v_write() 中,对 16bit 像素数据做字节交换:

/ 在 st7789v_write() 里,RAMWR 命令发送前 / row[w] = sys_cpu_to_be16(row[w]);

LVGL workqueue 模式:建议关闭(CONFIG_LV_Z_RUN_LVGL_ON_WORKQUEUE=n),在 main loop 中直接调用 lv_timer_handler()。

zephyr,display chosen:LVGL 自动从设备树的 chosen { zephyr,display } 获取显示设备驱动,不需要手动调用任何注册函数。

收藏 评论0 发布时间:2026-5-28 21:44

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版