硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3966|回复: 58
收起左侧

[LVGL] 基于V5,V6和V7的LVGL模板,驱动支持单缓冲,双缓冲和配合硬件消隐的双缓冲,以及电容和电阻触摸全支持(2023-07-19)

  [复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
发表于 2023-7-19 02:08:34 | 显示全部楼层 |阅读模式
V5是STM32F407IGT6,V6是STM32F429BIT6,V7是STM32H743XIH6/H750XB

1、优先安装MDK的LVGL软件包:

LVGL.lvgl.8.3.8.pack (4.76MB)

2、裸机模板下载:
V5-6001_LVGL8 Template(V1.0).7z (5.13MB)
V6-6001_LVGL8 Template(V1.0).7z (3.72MB)
V7-6001_LVGL8 Template(V1.0).7z (2.47MB)

本模板持续更新,持续优化维护,这几天增加MDK RTE一键添加FreeRTOS + LwIP + LVGL这种组合玩法模板。

程序说明:
1、LVGL版本使用的V8.3.8
2、MDK AC5编译,源码本身有一些警告,不用管。
3、自适应V5, V6,V7的4.3寸,5寸和7寸屏,包含电阻触摸和电容。
4、采样MDK RTE一键创建LVGL工程。
5、由于当前的LVGLV8.X不支持多任务,所以移植到任何RTOS上均不涉及到底层接口处理问题,跟裸机使用一样。
6、lv_port_disp_template.c文件做了三种模式支持,其中双缓冲配合硬件垂直消隐可以有效解决显示撕裂问题,V6和V7支持这种方式,V5不支持。

驱动模式,通过开头的宏定义选择:

#define CreateOnebuffer   
//#define CreateTWObuffer
//#define Doublebuffering

[C] 纯文本查看 复制代码
/**
 * @file lv_port_disp_templ.c
 *
 */

/*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
#if 1

/*********************
 *      INCLUDES
 *********************/
#include "lv_port_disp_template.h"
#include <stdbool.h>
#include "lvgl.h"

#include "bsp.h"

/*********************
 *      DEFINES
 *********************/
 #ifndef      __MEMORY_AT
  #if     (defined (__CC_ARM))
    #define  __MEMORY_AT(x)     __attribute__((at(x)))
  #elif   (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
    #define  __MEMORY_AT__(x)   __attribute__((section(".bss.ARM.__at_"#x)))
    #define  __MEMORY_AT(x)     __MEMORY_AT__(x)
  #else
    #define  __MEMORY_AT(x)
    #warning Position memory containing __MEMORY_AT macro at absolute address!
  #endif
#endif

#ifndef MY_DISP_HOR_RES
    #define MY_DISP_HOR_RES    800
#endif

#ifndef MY_DISP_VER_RES
    #define MY_DISP_VER_RES    480
#endif

#define CreateOnebuffer
//#define CreateTWObuffer
//#define Doublebuffering

/**********************
 *      TYPEDEFS
 **********************/
static __IO int8_t wTransferState;
extern LTDC_HandleTypeDef   hltdc_F;

/* 注意bsp_tft_h7.c文件使能了行中断和NVIC */
void LTDC_IRQHandler(void) 
{
        LTDC->ICR = (uint32_t)LTDC_IER_LIE;
        wTransferState = 1;
}

/**********************
 *  STATIC PROTOTYPES
 **********************/
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);

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();

    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/

    /**
     * LVGL requires a buffer where it internally draws the widgets.
     * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
     * The buffer has to be greater than 1 display row
     *
     * There are 3 buffering configurations:
     * 1. Create ONE buffer:
     *      LVGL will draw the display's content here and writes it to your display
     *
     * 2. Create TWO buffer:
     *      LVGL will draw the display's content to a buffer and writes it your display.
     *      You should use DMA to write the buffer's content to the display.
     *      It will enable LVGL to draw the next part of the screen to the other buffer while
     *      the data is being sent form the first buffer. It makes rendering and flushing parallel.
     *
     * 3. Double buffering
     *      Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
     *      This way LVGL will always provide the whole rendered screen in `flush_cb`
     *      and you only need to change the frame buffer's address.
     */

    /* Example for 1) */
#ifdef CreateOnebuffer
    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_1[MY_DISP_HOR_RES * 200];                          /*A buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 200);   /*Initialize the display buffer*/

    /* Example for 2) */
#elif defined CreateTWObuffer
    static lv_disp_draw_buf_t draw_buf_dsc_2;
    static lv_color_t buf_2_1[MY_DISP_HOR_RES * 50];                        /*A buffer for 10 rows*/
    static lv_color_t buf_2_2[MY_DISP_HOR_RES * 50];                        /*An other buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 50);   /*Initialize the display buffer*/

    /* Example for 3) also set disp_drv.full_refresh = 1 below*/
#elif defined Doublebuffering
    static lv_disp_draw_buf_t draw_buf_dsc_3; 
    static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES] __MEMORY_AT(0xC0000000);  /*A screen sized buffer*/
    static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES] __MEMORY_AT(0xC00BB800);  /*Another screen sized buffer*/

        lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2,
                                                        MY_DISP_VER_RES * MY_DISP_HOR_RES);   /*Initialize the display buffer*/
#endif

    /*-----------------------------------
     * Register the display in LVGL
     *----------------------------------*/

    static lv_disp_drv_t disp_drv;                  /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/
        switch (g_LcdType)
        {
                case LCD_43_480X272:                /* 4.3寸 480 * 272 */        
                case LCD_50_480X272:                /* 5.0寸 480 * 272 */
                         /*Set the resolution of the display*/
                        disp_drv.hor_res = 480;
                        disp_drv.ver_res = 272;
                        break;
                
                case LCD_50_800X480:                /* 5.0寸 800 * 480 */
                case LCD_70_800X480:                /* 7.0寸 800 * 480 */        
                        disp_drv.hor_res = 800;
                        disp_drv.ver_res = 480;
                        break;
                
                default:        
                        break;
        }
  
    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = disp_flush;

#ifdef CreateOnebuffer
    /*Set a display buffer*/
    disp_drv.draw_buf = &draw_buf_dsc_1;
#elif defined CreateTWObuffer
    /*Set a display buffer*/
    disp_drv.draw_buf = &draw_buf_dsc_2;        
#elif defined Doublebuffering
    /*Set a display buffer*/
    disp_drv.draw_buf = &draw_buf_dsc_3;        
        /*Required for Example 3)*/
        disp_drv.full_refresh = 1;        
#endif
        
        wTransferState = 0;
        
    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
}

volatile bool disp_flush_enabled = true;

/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL
 */
void disp_enable_update(void)
{
    disp_flush_enabled = true;
}

/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL
 */
void disp_disable_update(void)
{
    disp_flush_enabled = false;
}

#ifndef Doublebuffering
static void _DMA2D_Copy(void * pSrc, 
                            void * pDst, 
                                                uint32_t xSize, 
                                                uint32_t ySize, 
                                                uint32_t OffLineSrc, 
                                                uint32_t OffLineDst, 
                                                uint32_t PixelFormat) 
{

        /* DMA2D采用存储器到存储器模式, 这种模式是前景层作为DMA2D输入 */  
        DMA2D->CR      = 0x00000000UL | (1 << 9);
        DMA2D->FGMAR   = (uint32_t)pSrc;
        DMA2D->OMAR    = (uint32_t)pDst;
        DMA2D->FGOR    = OffLineSrc;
        DMA2D->OOR     = OffLineDst;
        
        /* 前景层和输出区域都采用的RGB565颜色格式 */
        DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
        DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_RGB565;
        
        DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize;

        /* 启动传输 */
        DMA2D->CR   |= DMA2D_CR_START;   

        /* 等待DMA2D传输完成 */
        while (DMA2D->CR & DMA2D_CR_START) {} 
}
#endif

/*Flush the content of the internal buffer the specific area on the display
 *You can use DMA or any hardware acceleration to do this operation in the background but
 *'lv_disp_flush_ready()' has to be called when finished.*/
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{

#ifndef  Doublebuffering
        int32_t x;
    int32_t y;
        
        x = area->x2 - area->x1 +1;  
        y = area->y2 - area->y1 +1;
                
        _DMA2D_Copy((void *)(color_p), 
                        (void *)(EXT_SDRAM_ADDR+disp_drv->hor_res*area->y1*2+ area->x1*2), 
                                x, 
                                y, 
                                0, 
                                disp_drv->hor_res - x, 
                                LTDC_PIXEL_FORMAT_RGB565);
#else
        while (wTransferState== 0){}
        wTransferState = 0;

        __HAL_LTDC_LAYER(&hltdc_F, 0)->CFBAR =(uint32_t)color_p;
        __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc_F);        
#endif
                
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

#else /*Enable this file at the top*/

/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif


单缓冲:

下载.png

双缓冲+硬件垂直消隐

12.png

RA8875屏截图:



STM32F407+LVGL8+RA8875+外部SRAM,视频展示800*480做滑动效果流畅度也不错



MDK RTE一键添加:

下载 (1).png







回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-7-19 02:08:43 | 显示全部楼层
更新完毕。
回复

使用道具 举报

44

主题

562

回帖

699

积分

金牌会员

积分
699
发表于 2023-7-19 08:34:32 | 显示全部楼层
下载学习看看,好像还没有添加SDRAM的支持哦
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-7-19 09:27:46 | 显示全部楼层
ou513 发表于 2023-7-19 08:34
下载学习看看,好像还没有添加SDRAM的支持哦

V6的内部SRAM小,我全部开到SDRAM了,V7的内部SRAM大,我部分开到了内部SRAM,部分开到SDRAM。

[C] 纯文本查看 复制代码
    /* Example for 1) */
#ifdef CreateOnebuffer
    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_1[MY_DISP_HOR_RES * 5000]__MEMORY_AT(0xC0800000);     /*A buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 5000); /*Initialize the display buffer*/

    /* Example for 2) */
#elif defined CreateTWObuffer
    static lv_disp_draw_buf_t draw_buf_dsc_2;
    static lv_color_t buf_2_1[MY_DISP_HOR_RES * 2500]__MEMORY_AT(0xC0800000);           /*A buffer for 10 rows*/
    static lv_color_t buf_2_2[MY_DISP_HOR_RES * 2500]__MEMORY_AT(0xC0C00000);           /*An other buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 2500);   /*Initialize the display buffer*/

    /* Example for 3) also set disp_drv.full_refresh = 1 below*/
#elif defined Doublebuffering
    static lv_disp_draw_buf_t draw_buf_dsc_3; 
    static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES] __MEMORY_AT(0xC0000000);  /*A screen sized buffer*/
    static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES] __MEMORY_AT(0xC00BB800);  /*Another screen sized buffer*/

        lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2,
                                                        MY_DISP_VER_RES * MY_DISP_HOR_RES);   /*Initialize the display buffer*/
#endif


V5的话,我全部开到外部SRAM
[C] 纯文本查看 复制代码
    /* Example for 1) */
#ifdef CreateOnebuffer
    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_1[MY_DISP_HOR_RES * 500]__MEMORY_AT(EXT_SRAM_ADDR);        /*A buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 500);   /*Initialize the display buffer*/

    /* Example for 2) */
#elif defined CreateTWObuffer
    static lv_disp_draw_buf_t draw_buf_dsc_2;
    static lv_color_t buf_2_1[MY_DISP_HOR_RES * 15]__MEMORY_AT(0x10000000);           /*A buffer for 10 rows*/
    static lv_color_t buf_2_2[MY_DISP_HOR_RES * 15]__MEMORY_AT(0x10008000);           /*An other buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 15);   /*Initialize the display buffer*/
#endif




回复

使用道具 举报

44

主题

562

回帖

699

积分

金牌会员

积分
699
发表于 2023-7-19 13:48:19 | 显示全部楼层
看的是V7版本的代码,没有太注意有条件编译,如果是定义这个 Doublebuffering 就是外部SDRAM,但代码里DMA2D是不能定义Doublebuffering,疑惑就是定义了双缓存用SDRAM那就不能用DMA2D了吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-7-19 14:46:31 | 显示全部楼层
ou513 发表于 2023-7-19 13:48
看的是V7版本的代码,没有太注意有条件编译,如果是定义这个 Doublebuffering 就是外部SDRAM,但代码里DMA2 ...

这就是大家在移植LVGL的Doublebuffering时容易搞错的原因,LVGL这里仅仅需要切换双缓冲地址,不需要做任何额外的操作,这个接口函数在Doublebuffering方式下,仅仅起到一个地址切换并告诉LVGL库的作用。

而DMA2D加速是在另外的接口重定向方式里面起作用的,也就MDK RTE添加的这个文件,F429,H7等系列可以勾选这个

下载 (2).png
回复

使用道具 举报

44

主题

562

回帖

699

积分

金牌会员

积分
699
发表于 2023-7-20 16:56:57 | 显示全部楼层
如果是这样我就是理解错了,还一直在想找双缓存+SDRAM+DAM2D的方案想做优化。掉坑里了,用LVGL做了一个项目,基本完成了但是感觉刷不是很流畅,特别是用LVGL自带的控件chart刷波形,能感觉到比较卡,其他页面就还比较好。
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
发表于 2023-7-21 16:14:49 | 显示全部楼层
下载的是V6的工程包,直接编译会出现一堆提示,都是找不到“lv_conf.h”。需要修改什么吗?
微信图片_20230721161339.png
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-7-21 16:21:45 | 显示全部楼层
gzw19900817 发表于 2023-7-21 16:14
下载的是V6的工程包,直接编译会出现一堆提示,都是找不到“lv_conf.h”。需要修改什么吗?

貌似是你的软件包弄的太深了,MDK无法正常检索到。
回复

使用道具 举报

6

主题

130

回帖

148

积分

初级会员

积分
148
发表于 2023-7-26 10:03:39 | 显示全部楼层
下载试了下,V7,使用双缓冲(Doublebuffering),滑动界面的时候,还是有肉眼可见的撕裂感。另外,感觉lvgl这个FPS的统计,好像有点不太对。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-7-27 07:19:02 | 显示全部楼层
cjunrong 发表于 2023-7-26 10:03
下载试了下,V7,使用双缓冲(Doublebuffering),滑动界面的时候,还是有肉眼可见的撕裂感。另外,感觉lvg ...

1、LVGL的FPS统计确实比较诡异。
2、如果是V7板子和V7对应的显示屏,效果还是可以的,几乎看不到撕裂,注意我分享的例子,LTDC时钟我是调节过的。这个时间决定垂直消隐的时间长短,这个是我的视频效果:






回复

使用道具 举报

6

主题

130

回帖

148

积分

初级会员

积分
148
发表于 2023-7-29 16:40:44 | 显示全部楼层
eric2013 发表于 2023-7-27 07:19
1、LVGL的FPS统计确实比较诡异。
2、如果是V7板子和V7对应的显示屏,效果还是可以的,几乎看不到撕裂, ...

是使用V7的板子和对应的显示屏,也是使用的楼主位的程序,唯独在柱状图那里会看到明显的撕裂感,其他的地方很难看到。
lvgl_撕裂.jpg
下面上传个视频(zip的压缩文件),不过感觉视频拍的不是很清晰,实际肉眼看的话会明显一些。

lvgl.zip (5.78 MB, 下载次数: 13)
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-7-29 17:31:55 | 显示全部楼层
cjunrong 发表于 2023-7-29 16:40
是使用V7的板子和对应的显示屏,也是使用的楼主位的程序,唯独在柱状图那里会看到明显的撕裂感,其他的地 ...

测试了,这个小柱的撕裂跟垂直消隐的撕裂不同,这个是滑动的时候刷新的太慢,没刷新过来,一下子撕裂了好几行

LVGL的这个控件实现应该不太好。
回复

使用道具 举报

6

主题

130

回帖

148

积分

初级会员

积分
148
发表于 2023-7-30 08:55:12 | 显示全部楼层
eric2013 发表于 2023-7-29 17:31
测试了,这个小柱的撕裂跟垂直消隐的撕裂不同,这个是滑动的时候刷新的太慢,没刷新过来,一下子撕裂了好 ...

明白
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
发表于 2023-8-1 16:34:59 | 显示全部楼层
可以切换显存区的操作放到行中断里面,不要在disp_flush函数里面等待刷新完成,像下面这样
static __IO int8_t *pLCD_buff;
void LTDC_IRQHandler(void)
{
        LTDC->ICR = (uint32_t)LTDC_IER_LIE;
        __HAL_LTDC_LAYER(&hltdc_F, 0)->CFBAR =(uint32_t)pLCD_buff;
        __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc_F);
}
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
pLCD_buff = (int8_t*)color_p;
    lv_disp_flush_ready(disp_drv);
}
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-8-1 17:05:06 | 显示全部楼层
strangeman 发表于 2023-8-1 16:34
可以切换显存区的操作放到行中断里面,不要在disp_flush函数里面等待刷新完成,像下面这样
static __IO in ...

实测不行,界面会一直闪烁。拖拽的时候闪烁的更厉害。
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
发表于 2023-8-1 17:57:57 | 显示全部楼层
eric2013 发表于 2023-8-1 17:05
实测不行,界面会一直闪烁。拖拽的时候闪烁的更厉害。

这个操作只限于双渲染区,且必须每次全刷新,你闪烁的原因应该是当前刷新的显存区和渲染的显存区是同一个buff。我这边测试得挺好,这是我的代码:

#define MY_DISP_HOR_RES    800
#define MY_DISP_VER_RES    480

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);

static __IO u32 lcd_ram_addr = 0xc0000000;
IRAM_ATTR void LTDC_IRQHandler(void)
{
        LTDC->ICR = 0x0f;

        LTDC_Layer1->CFBAR = lcd_ram_addr;
        LTDC->SRCR |= LTDC_SRCR_IMR;
}

void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    //LCD_Init();
        HAL_LTDC_ProgramLineEvent(&hltdc,6+6+480);
    HAL_NVIC_SetPriority(LTDC_IRQn, 0xE, 0);
        HAL_NVIC_EnableIRQ(LTDC_IRQn);

    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/

    static lv_disp_draw_buf_t draw_buf_dsc_2;
//    static lv_color_t buf_2_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];                        /*A buffer for 10 rows*/
    // static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10];                        /*An other buffer for 10 rows*/
        lv_color_t *buf = (lv_color_t*)(0xc0000000);
        lv_color_t *buf2 = (lv_color_t*)(0xc0000000+800*480*2);
    lv_disp_draw_buf_init(&draw_buf_dsc_2, buf, buf2, MY_DISP_HOR_RES * MY_DISP_VER_RES);   /*Initialize the display buffer*/

    static lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/
    disp_drv.hor_res = MY_DISP_HOR_RES;
    disp_drv.ver_res = MY_DISP_VER_RES;
    disp_drv.flush_cb = disp_flush;
    disp_drv.draw_buf = &draw_buf_dsc_2;
    disp_drv.full_refresh = 1;

    lv_disp_drv_register(&disp_drv);
}

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    // if(!is_LCD_off())
    {
        // s16 w = area->x2-area->x1+1;
        // s16 h = area->y2-area->y1+1;
        // LCD_Blt(area->x1,area->y1,w,h,(u16*)color_p);

        // LCD_Set_Windows(area->x1,area->y1,area->x2,area->y2);
        // LCD_W_Dat((const u8*)color_p,w*h*2);

        lcd_ram_addr = (u32)color_p;
    }
   
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-8-1 18:17:31 | 显示全部楼层
strangeman 发表于 2023-8-1 17:57
这个操作只限于双渲染区,且必须每次全刷新,你闪烁的原因应该是当前刷新的显存区和渲染的显存区是同一个 ...

LVGL的双缓冲同步做的不好,非常受到LTDC时钟刷新速度影响,不同的显示屏都要微调节才能稳定。

你的这个在我们的几个款显示屏都无法使用, 官方的例子,闪烁的厉害



回复

使用道具 举报

9

主题

103

回帖

130

积分

初级会员

积分
130
发表于 2023-8-11 18:33:48 | 显示全部楼层
在Doublebuffering模式下例程源码是:
while (wTransferState== 0){}
wTransferState = 0;
__HAL_LTDC_LAYER(&hltdc_F, 0)->CFBAR =(uint32_t)color_p;
__HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc_F);       
假如LTDC刷新速度比较快 已经进入中断把标志wTransferState 置一了,LTDC已经重新开始刷屏了刷到一半,LVGL刚好调用disp_flush函数那不是出现裂纹了?不应该改成这样吗?
wTransferState = 0;
while (wTransferState== 0){}
__HAL_LTDC_LAYER(&hltdc_F, 0)->CFBAR =(uint32_t)color_p;
__HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(&hltdc_F);       
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-8-12 00:49:34 | 显示全部楼层
xy201207 发表于 2023-8-11 18:33
在Doublebuffering模式下例程源码是:
while (wTransferState== 0){}
wTransferState = 0;

是这样的,就是改成你这样后,刷新率降低了10帧左右。 为了追求刷新率,我切换了下位置。

几乎看不到撕裂,还行。

回复

使用道具 举报

44

主题

562

回帖

699

积分

金牌会员

积分
699
发表于 2023-9-5 09:08:02 | 显示全部楼层
尝试了一下,这个驱动貌似不支持旋转,开旋转就卡了
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-9-5 09:11:23 | 显示全部楼层
ou513 发表于 2023-9-5 09:08
尝试了一下,这个驱动貌似不支持旋转,开旋转就卡了

对,还没有做旋转测试。
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2023-10-8 15:28:46 | 显示全部楼层
eric2013 发表于 2023-7-19 14:46
这就是大家在移植LVGL的Doublebuffering时容易搞错的原因,LVGL这里仅仅需要切换双缓冲地址,不需要做任 ...

v7.11的非全屏双缓冲和单缓冲类似机制,v8应该也是,全屏双缓冲就是只需要更换层,这篇博文有对比
https://blog.csdn.net/weixin_42914339/article/details/129640435
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2023-10-8 15:30:55 | 显示全部楼层
ou513 发表于 2023-7-20 16:56
如果是这样我就是理解错了,还一直在想找双缓存+SDRAM+DAM2D的方案想做优化。掉坑里了,用LVGL做了一个项目 ...

最快的是非全屏双缓冲,也有画面分割,理论可以解决。官方的全屏双缓冲是为了解决画面切割问题,速度确实慢。可以看博文的对比:https://blog.csdn.net/weixin_42914339/article/details/129640435
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-10-8 15:33:41 | 显示全部楼层
bbs 发表于 2023-10-8 15:28
v7.11的非全屏双缓冲和单缓冲类似机制,v8应该也是,全屏双缓冲就是只需要更换层,这篇博文有对比
https ...

本质就是一个东西,只是全屏可以配合垂直消隐来消除撕裂。
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2023-10-8 15:34:21 | 显示全部楼层
cjunrong 发表于 2023-7-26 10:03
下载试了下,V7,使用双缓冲(Doublebuffering),滑动界面的时候,还是有肉眼可见的撕裂感。另外,感觉lvg ...

撕裂是因为ltdc 和dma2d同时访问同个内存导致的,避免一下就不会
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-10-8 15:35:25 | 显示全部楼层
bbs 发表于 2023-10-8 15:30
最快的是非全屏双缓冲,也有画面分割,理论可以解决。官方的全屏双缓冲是为了解决画面切割问题,速度确实 ...

非全屏双缓冲看似帧率多,大屏实际操作起来,有很强得滞后感,从而产生卡顿得感觉。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-10-8 15:38:40 | 显示全部楼层
bbs 发表于 2023-10-8 15:34
撕裂是因为ltdc 和dma2d同时访问同个内存导致的,避免一下就不会

不是这个原因,关闭DMA2D,刷新这个控件也会撕裂。是19楼得原因。
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2023-10-8 15:47:14 | 显示全部楼层
eric2013 发表于 2023-10-8 15:33
本质就是一个东西,只是全屏可以配合垂直消隐来消除撕裂。

单缓冲是把需要刷新的区域依次放入缓冲区,刷完一个再计算刷第二个。非全屏双缓冲区则利用多一个缓冲区,让刷新的时候可以同时进行第二个区的计算。全屏双缓冲就不一样了,一次性将所有的更改都放在另一个缓冲区上,然后直接换层,所以不会有切割。当然,这样做的后果是需要进行帧同步,结果就是效率堪忧
回复

使用道具 举报

0

主题

5

回帖

5

积分

新手上路

积分
5
发表于 2023-10-8 15:53:19 | 显示全部楼层
eric2013 发表于 2023-10-8 15:35
非全屏双缓冲看似帧率多,大屏实际操作起来,有很强得滞后感,从而产生卡顿得感觉。

非全屏缓冲区的大小是比刷新区域小吗,如果是的话,刷新一个区就会拆分为几次进行刷新,lvgl帧率好像会计算进去
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-10-9 08:14:28 | 显示全部楼层
bbs 发表于 2023-10-8 15:47
单缓冲是把需要刷新的区域依次放入缓冲区,刷完一个再计算刷第二个。非全屏双缓冲区则利用多一个缓冲区, ...

后面LVGL还有必要像emWin那样支持下三缓冲,真正意义上的避免撕裂。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-10-9 08:15:22 | 显示全部楼层
bbs 发表于 2023-10-8 15:53
非全屏缓冲区的大小是比刷新区域小吗,如果是的话,刷新一个区就会拆分为几次进行刷新,lvgl帧率好像会计 ...

是的,而且这种非全屏没法利用垂直消隐,顿挫感很强。

LVGL提供的大部分例子都是这种整屏滑动的,所以这种感觉很明显,



回复

使用道具 举报

44

主题

562

回帖

699

积分

金牌会员

积分
699
发表于 2023-12-2 20:52:37 | 显示全部楼层
eric2013 发表于 2023-10-9 08:15
是的,而且这种非全屏没法利用垂直消隐,顿挫感很强。

LVGL提供的大部分例子都是这种整屏滑动的,所以 ...

硬汉,LVGL驱动有研究更新了吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-12-3 10:00:54 | 显示全部楼层
ou513 发表于 2023-12-2 20:52
硬汉,LVGL驱动有研究更新了吗?

楼主位的已经是新版了。
回复

使用道具 举报

1

主题

23

回帖

26

积分

新手上路

积分
26
发表于 2023-12-4 11:09:26 | 显示全部楼层
请问我们有个项目,800*480,MIPI屏,原来是竖屏显示,480*800的分辨率,转成横屏了现在,切换颜色都有明显的撕裂现象,这个需要怎么解决呢,谢谢!

界面切换有撕裂感.zip

3.72 MB, 下载次数: 1

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-12-4 14:41:55 | 显示全部楼层
Yue@123 发表于 2023-12-4 11:09
请问我们有个项目,800*480,MIPI屏,原来是竖屏显示,480*800的分辨率,转成横屏了现在,切换颜色都有明显 ...

你这个是手动旋转显存空间转的吗。
回复

使用道具 举报

1

主题

23

回帖

26

积分

新手上路

积分
26
发表于 2023-12-4 16:48:40 | 显示全部楼层
eric2013 发表于 2023-12-4 14:41
你这个是手动旋转显存空间转的吗。

#define LCD_DISP_ROTATION LCD_DISP_ROTATION_270
是改的这个地方
回复

使用道具 举报

1

主题

23

回帖

26

积分

新手上路

积分
26
发表于 2023-12-5 15:52:47 | 显示全部楼层
eric2013 发表于 2023-12-4 14:41
你这个是手动旋转显存空间转的吗。

如果保持这个MIPI屏原来的刷屏方向,竖向刷新的,也会有这个撕裂感,稍微轻一点,麻烦帮忙看看这个怎么能解决呢,多谢
回复

使用道具 举报

1

主题

23

回帖

26

积分

新手上路

积分
26
发表于 2023-12-21 14:49:19 | 显示全部楼层
eric2013 发表于 2023-12-4 14:41
你这个是手动旋转显存空间转的吗。

如果保持这个MIPI屏原来的刷屏方向,竖向刷新的,也会有这个撕裂感,稍微轻一点,麻烦帮忙看看这个怎么能解决呢,多谢

---能帮忙给下关于这个问题的意见吗?是硬件的问题,还是屏的驱动的问题?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106721
QQ
 楼主| 发表于 2023-12-22 08:59:46 | 显示全部楼层
Yue@123 发表于 2023-12-21 14:49
如果保持这个MIPI屏原来的刷屏方向,竖向刷新的,也会有这个撕裂感,稍微轻一点,麻烦帮忙看看这个怎么能 ...

刷跟我楼主位一样的demo也撕裂吗,这个也撕裂的话,不正常。

垂直消隐没处理好。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-1 08:21 , Processed in 0.467456 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表