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

【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中文论坛活动

即日起开启活动话题入口,之后的活动统一都放在此处,欢迎大家的加入!


最新内容

相似分享

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