【LVGL】显示驱动移植,控件显示错乱的解决办法

本文介绍了如何将LVGL移植到采用SPI接口的ST7735显示驱动中,包括disp_flush和disp_init函数的实现,以及在移植过程中遇到的问题和解决方案,着重于屏幕分辨率的初始化对显示效果的影响。
摘要由CSDN通过智能技术生成

一、Intro

LVGL官方提供了lv_port_disp_template.c文件,包含显示初始化函数static void disp_init(void);
以及显示刷新函数static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);

我们移植LVGL显示驱动的主要工作就是将上述两个函数用自己的屏幕驱动实现,比如我这里采用的是SPI接口的ST7735驱动。

二、移植过程

1.实现显示刷新函数disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)。有它三个参数,分别为显示驱动对象、坐标数据以及颜色数据。

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /* 打点填充 */
//    int32_t x;
//    int32_t y;
//    for(y = area->y1; y <= area->y2; y++) {
//        for(x = area->x1; x <= area->x2; x++) {
//            /*Put a pixel to the display. For example:*/
//            /*put_px(x, y, *color_p)*/
//            color_p++;
//        }
//    }

    /* 区域填充 */
    lcd_color_fill(area->x1, area->y1, area->x2, area->y2, (uint16_t *)color_p);

    /* 刷新完毕 */
    lv_disp_flush_ready(disp_drv);
}

对于disp_flush函数,有两种实现方法。一种是打点填充,这种方法每次写入输入都需要指定对应的地址,效率比较低。另一种方法则是区域填充,即在写入之前先指定起始和结束地址,然后一次性写入。推荐使用第二种方法来实现显示刷新操作。
待实现的填充函数lcd_color_fill(area->x1, area->y1, area->x2, area->y2, (uint16_t *)color_p)有5个参数,分别为起点xy坐标、终点xy坐标以及对应的颜色数组。lv_color_t是一个typedef定义的类型,它被定义为union类型lv_color16_tlv_color16_t类型如下所示。

typedef union {
    struct {
#if LV_COLOR_16_SWAP == 0
        uint16_t blue : 5;
        uint16_t green : 6;
        uint16_t red : 5;
#else
        uint16_t green_h : 3;
        uint16_t red : 5;
        uint16_t blue : 5;
        uint16_t green_l : 3;
#endif
    } ch;
    uint16_t full;
} lv_color16_t;

lv_color16_t的定义中我们可以知道其大小就相当于一个uint16_t类型。lv_color_t * color_p指向了一段连续的颜色数组空间,我们可以使用color_p->full取出每个对应的颜色数据,通过color_p++来遍历操作。当然,也可以将其强制转换为uint16_t类型(uint16_t *) color_p,直接使用*color_p来取出对应的颜色数据。

2.在disp_init()中放入我们的LCD初始化函数

static void disp_init(void)
{
    /*You code here*/
    lcd_init();         /* 初始化LCD */
}

3.修改宏定义适配自己的屏幕大小

#define MY_DISP_HOR_RES (128)   /* 屏幕宽度 */
#define MY_DISP_VER_RES (160)   /* 屏幕高度 */

三、问题

本来以为到这里就万事大吉了,没想到跑起来后按钮控件直接裂开(字面意义上的)。然后,才发现在void lv_port_disp_init(void)函数中同样需要修改屏幕分辨率,用来 初始化对象参数。

disp_drv.hor_res = MY_DISP_HOR_RES;
disp_drv.ver_res = MY_DISP_VER_RES;

这样修改后显示刷新就正常了。
(注:如果没有正确初始化分辨率,采用打点填充的方式,控件可能显示正常,但坐标会异常)

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chvngzhvng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值