求助,有趣的LVGL驱动ILI9488,屏幕边缘有一排亮点。[已解决]

ESP32踩坑者1
Posts: 13
Joined: Mon Dec 20, 2021 4:34 pm

求助,有趣的LVGL驱动ILI9488,屏幕边缘有一排亮点。[已解决]

Postby ESP32踩坑者1 » Mon Jun 13, 2022 6:30 am

这几天我用ESP32通过LVGL成功驱动了一块ILI9488的TFT。
但是遇到一个问题始终不能解决。
无论我放置什么组件到屏幕的右侧边缘(屏幕的 x = 0 在最左边)总会出现一串亮点,并且有从上到下越来越亮的现象。

效果是这样:
[attachment=1]微信图片_40.jpg[/attachment]
或者这样:
[attachment=0]微信图片_20.jpg[/attachment]

是不是很有趣的现象?

起初问题的表现为图1,经过我的观察,总共有8个亮点,而我的屏幕y轴分辨率为 320.
仔细思考后,猜测,是否再刷新LCD时,LVGL把整个屏幕分成了8块,而每一块的最后一个点数据错误,导致变色。
随后我更改了 lvgl_helpers.h 中的这个宏定义:
#elif defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_ILI9488
#define DISP_BUF_SIZE (LV_HOR_RES_MAX * 40) /* 我将 40 改为20 */
因为 40 * 8 刚好是 320 , 而他定义的 DISP_BUF_SIZE 是屏幕宽度(480)的 40 倍,这样算下来刚好 8 次刷满一个屏幕。
现在我把常数 40 改为 20 , 会不会出现16个渐渐变亮的点呢?
图2,正是我修改后的结果。不多不少整整16个。

后来我又怀疑是不是屏幕本身的质量问题,导致了这样的结果。经过反复测试,无论我把屏幕定义为多大,
也就是:
#define LV_HOR_RES_MAX 480
#define LV_VER_RES_MAX 320
这无论无何改变,所规定的屏幕边缘区域都会出现这样一排亮点。
也就是说 如果我把屏幕变为 LV_HOR_RES_MAX 320 ,假设是一块320 x 320的屏幕,在屏幕 X = 320 的纵轴上依然会出现这样的亮点。

下面是我目前的代码:

1>gui任务初始化部分

static void guiTask(void *pvParameter)
{
(void)pvParameter;
xGuiSemaphore = xSemaphoreCreateMutex();
lv_init();

/* Initialize SPI or I2C bus used by the drivers */
lvgl_driver_init();

lv_color_t *buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1 != NULL);

static lv_color_t *buf2 = NULL;

static lv_disp_draw_buf_t disp_buf;

uint32_t size_in_px = DISP_BUF_SIZE; /* 就是这里传入了显示BUFF的大小 480 x 40 */

/* Initialize the working buffer depending on the selected display.
* NOTE: buf2 == NULL when using monochrome displays. */
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, size_in_px);

lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.flush_cb = disp_driver_flush;
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;

disp_drv.draw_buf = &disp_buf;
lv_disp_drv_register(&disp_drv);

/* Register an input device when enabled on the menuconfig */
#if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.read_cb = touch_driver_read;
indev_drv.type = LV_INDEV_TYPE_POINTER;
lv_indev_drv_register(&indev_drv);
#endif

/* Create and start a periodic timer interrupt to call lv_tick_inc */
const esp_timer_create_args_t periodic_timer_args = {
.callback = &lv_tick_task,
.name = "periodic_gui"};
esp_timer_handle_t periodic_timer;
ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, portTICK_PERIOD_MS * 1000));

/* Create the demo application */
create_demo_application();

while (1)
{
/* Delay 1 tick (assumes FreeRTOS tick is 10ms */
vTaskDelay(pdMS_TO_TICKS(10));

/* Try to take the semaphore, call lvgl related function on success */
if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
{
lv_task_handler();
xSemaphoreGive(xGuiSemaphore);
}
}

/* A task should NEVER return */
free(buf1);
#ifndef CONFIG_LV_TFT_DISPLAY_MONOCHROME
free(buf2);
#endif
vTaskDelete(NULL);
}

2>界面实体部分
LV_IMG_DECLARE(back_img); /* 用于桌面背景的图片 size = 480 x 320 */
static void create_demo_application(void)
{
#if 1 /* 这里显示的图片就是背景图片,图片本身没有问题,我也用纯色的图片测试过,甚至改变桌面的颜色 结果都一样 */
lv_obj_t *back_img_hal = lv_img_create(lv_scr_act());
lv_img_set_src(back_img_hal, &back_img);
lv_obj_align(back_img_hal, LV_ALIGN_TOP_LEFT, 0, 0);

....以下绘制了一些用于显示内容的 box ,无论是否编译对该问题没有影响。
.
.
.
.
.
}

有没有大神帮忙分析一下,问题出在哪里?我该如何处理?
谢谢您的解答,不甚感激!
Attachments
微信图片_20.jpg
微信图片_20.jpg (364.92 KiB) Viewed 6701 times
微信图片_40.jpg
微信图片_40.jpg (331.64 KiB) Viewed 6701 times

ESP32踩坑者1
Posts: 13
Joined: Mon Dec 20, 2021 4:34 pm

Re: 求助,有趣的LVGL驱动ILI9488,屏幕边缘有一排亮点。

Postby ESP32踩坑者1 » Mon Jun 13, 2022 6:31 am

排版出了点问题,图片位置怎么跑到最后去了。还有代码没有了缩进。

ESP32踩坑者1
Posts: 13
Joined: Mon Dec 20, 2021 4:34 pm

Re: 求助,有趣的LVGL驱动ILI9488,屏幕边缘有一排亮点。

Postby ESP32踩坑者1 » Mon Jun 13, 2022 6:44 am

有木有人啊?给个建议也好啊~!~~~

ESP32踩坑者1
Posts: 13
Joined: Mon Dec 20, 2021 4:34 pm

Re: 求助,有趣的LVGL驱动ILI9488,屏幕边缘有一排亮点。

Postby ESP32踩坑者1 » Mon Jun 13, 2022 9:30 am

求人不如求己,问题找到了。也从一定程度上解决了。但是本质问题还没找到,目前采用补窟窿的方式解决的。
在这里留个记号,如果有朋友遇到此问题可以这样解决或者大家一起讨论。

LVGL刷屏的本质动作是 , 设定起点坐标和终点坐标, 用连续传输模式,使用DMA传输。
在每一次传输一块图像前,都有
/*Column addresses*/
ili9488_send_cmd(ILI9488_CMD_COLUMN_ADDRESS_SET);
ili9488_send_data(xb, 4);/* 起点X 终点X 每个占用2字节 */

/*Page addresses*/
ili9488_send_cmd(ILI9488_CMD_PAGE_ADDRESS_SET);
ili9488_send_data(yb, 4);/* 起点Y 终点Y 每个占用2字节 */
我以前不上GUI的时候,采用的是只设置起点,并用连续模式传输多少个点,来完成的。
他设置了起点和终点。这是一种什么思路?我是真的不懂,请指教。
他每次传输的块的大小等于你设定的 (屏幕宽度 * 40),单位是点。
每次回调 flush 都是只刷新 这么大一块。

可是问题就就就出现在 假设我连续传输 sum 个点,理论上是 buf[0]~buf[sum-1],
可是就是这个 buf[sum - 1] 不会被正确的传输,可能根本就没传输?。经过验证,所申请的DMA空间的该reg的值是正确的。

可能是我线长的问题,毕竟用的杜邦线。
也可能是底层驱动的BUG.这个等我画好板子,再测试。

目前解决方案:
/* 该函数在flush 最后调用 */
ili9488_send_color((void *) mybuf, size * 3); /* 原本的 */
ili9488_send_color((void *) (&mybuf[size*3]), 3); /* 我添加的,实际上就是把最后一个点手动画了一次,问题就这么被我糊弄过去了 */
// free buff .. fun end

yangyang
Posts: 7
Joined: Mon Jun 06, 2022 7:09 am

Re: 求助,有趣的LVGL驱动ILI9488,屏幕边缘有一排亮点。

Postby yangyang » Tue Jun 28, 2022 8:13 am

我也试了一下你的方法,之前我就怀疑是缺失一些字节的问题,我怀疑过dma或者spi总线问题,通过调整lvgl缓冲buff大小那个点点的数量也会相应的变多或者变小

asd3330303
Posts: 5
Joined: Thu May 05, 2022 1:50 am

Re: 求助,有趣的LVGL驱动ILI9488,屏幕边缘有一排亮点。[已解决]

Postby asd3330303 » Wed Aug 09, 2023 3:29 pm

参考楼主的,已解决问题哈哈,这个问题卡了我半年
在函数void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
里最后
ili9488_send_color((void *) mybuf, size * 3);
ili9488_send_color((void *) (&mybuf[(size*3) - 3]), 3);//增加的
heap_caps_free(mybuf);

asd3330303
Posts: 5
Joined: Thu May 05, 2022 1:50 am

Re: 求助,有趣的LVGL驱动ILI9488,屏幕边缘有一排亮点。[已解决]

Postby asd3330303 » Wed Aug 09, 2023 5:26 pm

根因已找到了,是因为数据加入发送队列的之后,我们就free掉buffer了,所以存在野数据问题,野数据是导致亮点的原因。在发送和free之间加入disp_wait_for_pending_transactions();也可以解决这问题(弊端是会降低刷新率,这部分弊端和楼主的解决方案是一样的)。

完美解决方案如下
  1. void ili9488_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
  2. {
  3.     uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);
  4.  
  5.     lv_color16_t *buffer_16bit = (lv_color16_t *) color_map;
  6.     static uint8_t *mybuf = NULL;
  7.  
  8.     if (mybuf != NULL){
  9.         disp_wait_for_pending_transactions();//等待发完后重新申请地址
  10.         heap_caps_free(mybuf);
  11.         mybuf = NULL;
  12.     }
  13.  
  14.     do {
  15.         mybuf = (uint8_t *) heap_caps_malloc(3 * size * sizeof(uint8_t), MALLOC_CAP_DMA);
  16.         if (mybuf == NULL)  ESP_LOGW(TAG, "Could not allocate enough DMA memory!");
  17.     } while (mybuf == NULL);
  18.  
  19.     uint32_t LD = 0;
  20.     uint32_t j = 0;
  21.  
  22.     for (uint32_t i = 0; i < size; i++) {
  23.         LD = buffer_16bit[i].full;
  24.         mybuf[j] = (uint8_t) (((LD & 0xF800) >> 8) | ((LD & 0x8000) >> 13));
  25.         j++;
  26.         mybuf[j] = (uint8_t) ((LD & 0x07E0) >> 3);
  27.         j++;
  28.         mybuf[j] = (uint8_t) (((LD & 0x001F) << 3) | ((LD & 0x0010) >> 2));
  29.         j++;
  30.     }
  31.  
  32.     /* Column addresses  */
  33.     uint8_t xb[] = {
  34.         (uint8_t) (area->x1 >> 8) & 0xFF,
  35.         (uint8_t) (area->x1) & 0xFF,
  36.         (uint8_t) (area->x2 >> 8) & 0xFF,
  37.         (uint8_t) (area->x2) & 0xFF,
  38.     };
  39.    
  40.     /* Page addresses  */
  41.     uint8_t yb[] = {
  42.         (uint8_t) (area->y1 >> 8) & 0xFF,
  43.         (uint8_t) (area->y1) & 0xFF,
  44.         (uint8_t) (area->y2 >> 8) & 0xFF,
  45.         (uint8_t) (area->y2) & 0xFF,
  46.     };
  47.  
  48.     /*Column addresses*/
  49.     ili9488_send_cmd(ILI9488_CMD_COLUMN_ADDRESS_SET);
  50.     ili9488_send_data(xb, 4);
  51.  
  52.     /*Page addresses*/
  53.     ili9488_send_cmd(ILI9488_CMD_PAGE_ADDRESS_SET);
  54.     ili9488_send_data(yb, 4);
  55.  
  56.     /*Memory write*/
  57.     ili9488_send_cmd(ILI9488_CMD_MEMORY_WRITE);
  58.  
  59.     ili9488_send_color((void *) mybuf, size * 3);
  60.    
  61.     // heap_caps_free(mybuf);
  62. }

Who is online

Users browsing this forum: No registered users and 146 guests