2. 标签控件显示与动态文本更新
任务说明
本案例面向一块具体的嵌入式屏幕(例如 320×240 的 RGB 接口 LCD),需要完成两件事:一是根据屏幕的物理尺寸与像素分辨率,正确初始化 LVGL 的显示缓冲区与刷新回调;二是让 LVGL 的坐标系统与屏幕像素一一对应,确保绘制任何控件都不会出现偏移、截断或拉伸。最终通过一个简单的全屏着色与坐标探针控件,验证显示区域完全覆盖屏幕且坐标原点在左上角。
硬件与依赖假设
本案例以常见的 ST7789 驱动、320×240 分辨率、RGB 565 色彩格式的 SPI 接口屏幕为例。实际项目中,你只需要替换为所用屏幕的驱动初始化函数与像素写入函数即可。LVGL 版本要求 v8.x,并已正确移植了 lv_port_disp 模板文件。
核心实现
LVGL 的显示适配核心在于三个参数:水平分辨率、垂直分辨率和缓冲区策略。以下代码在 lv_conf.h 中完成基础配置,并在显示驱动初始化文件中设置正确的分辨率和刷新回调。
/* lv_conf.h 中与显示相关的关键配置 */
#define LV_COLOR_DEPTH 16 /* RGB565 */
#define LV_HOR_RES_MAX 320 /* 屏幕物理像素宽 */
#define LV_VER_RES_MAX 240 /* 屏幕物理像素高 */
#define LV_DPI_DEF 96 /* 逻辑DPI,用于字体缩放参考 */
/* disp_drv.c —— 显示驱动初始化与刷新回调 */
#include "lvgl.h"
#include "st7789.h" /* 假设已有屏幕驱动,提供 st7789_init() 和 st7789_fill_rect() */
/* 显示缓冲区:使用两个半帧缓冲区,便于LVGL后台刷新 */
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf_1[320 * 40]; /* 每行320像素,40行高 */
static lv_color_t buf_2[320 * 40];
/* 刷新回调:将LVGL渲染好的缓冲区内容写入屏幕 */
static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
/* 将像素数据按区域直接交给屏幕驱动 */
st7789_fill_rect(area->x1, area->y1, area->x2, area->y2,
(uint16_t *)&color_p->full);
lv_disp_flush_ready(disp_drv); /* 通知LVGL本次刷新完成 */
}
/* 显示驱动初始化 —— 在 main() 中调用 */
void lv_port_disp_init(void)
{
/* 初始化屏幕硬件 */
st7789_init();
/* 初始化LVGL显示缓冲区 */
lv_disp_draw_buf_init(&draw_buf, buf_1, buf_2, sizeof(buf_1) / sizeof(lv_color_t));
/* 注册显示驱动 */
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = 320; /* 必须与屏幕物理分辨率一致 */
disp_drv.ver_res = 240;
disp_drv.flush_cb = disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
}
验证方法
完成上述初始化后,在 main() 中调用 lv_port_disp_init(),然后创建一个覆盖全屏的纯色对象和一个坐标探针标签,用于直观判断适配是否正确。
/* main.c 中的验证代码 */
void create_verification_ui(void)
{
/* 1. 全屏红色背景:若分辨率适配错误,会出现未覆盖区域或颜色溢出 */
lv_obj_t *bg = lv_obj_create(lv_scr_act());
lv_obj_set_size(bg, 320, 240);
lv_obj_set_pos(bg, 0, 0);
lv_obj_set_style_bg_color(bg, lv_color_hex(0xFF0000), 0);
/* 2. 在屏幕四个角落放置小圆点,用于检测坐标偏移 */
lv_obj_t *dot_tl = lv_obj_create(lv_scr_act());
lv_obj_set_size(dot_tl, 10, 10);
lv_obj_set_pos(dot_tl, 0, 0);
lv_obj_set_style_bg_color(dot_tl, lv_color_hex(0x00FF00), 0);
lv_obj_t *dot_br = lv_obj_create(lv_scr_act());
lv_obj_set_size(dot_br, 10, 10);
lv_obj_set_pos(dot_br, 310, 230); /* 320-10=310, 240-10=230 */
lv_obj_set_style_bg_color(dot_br, lv_color_hex(0x00FF00), 0);
/* 3. 中心位置显示分辨率文本,便于肉眼确认 */
lv_obj_t *label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "320x240");
lv_obj_center(label);
}
int main(void)
{
lv_init();
lv_port_disp_init(); /* 分辨率适配的关键初始化 */
create_verification_ui();
while (1) {
lv_timer_handler();
delay_ms(5);
}
}
判定标准
- 屏幕完全显示红色且无黑边、无溢出,说明
hor_res与ver_res设置正确; - 左上角与右下角的绿色圆点完整可见且紧贴屏幕边缘,说明坐标原点与像素映射无偏移;
- 中心文字“320x240”清晰无变形,说明像素格式与缓冲区大小匹配。
常见问题排查
- 画面偏移但尺寸正确:检查
st7789_fill_rect的坐标是否从 0 开始,部分屏幕驱动需要设置列/行偏移寄存器(如 ST7789 的 MADCTL)。 - 画面闪烁或撕裂:缓冲区过小或未使用双缓冲,可增大缓冲区高度或启用 LVGL 的
LV_COLOR_SCREEN_TRANSP相关优化。 - 颜色显示异常:确认
LV_COLOR_DEPTH与屏幕驱动的 RGB 格式一致,RGB565 与 RGB888 混用会导致颜色错乱。