I’m trying to get the 5" Elecrow display (SKU: DIS0705H) working, but it’s not functioning properly.
The problem is that the example provided by Elecrow is an old example (ESP IDF 4) and uses Arduino libraries.
I’m trying to make it work properly using Expressif components, avoiding the workaround of using Arduino libraries.
The code that displays the screen is below:
f_elecrow_5In.c:
#include "f_elecrow_5in.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_lcd_panel_rgb.h"
#include "esp_lcd_panel_ops.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
esp_err_t elecrow_5in_init(esp_lcd_panel_handle_t *out_panel)
{
esp_lcd_rgb_panel_config_t cfg = {
.clk_src = LCD_CLK_SRC_PLL160M,
.data_width = 16,
.bits_per_pixel = 16,
.de_gpio_num = GPIO_NUM_40,
.vsync_gpio_num = GPIO_NUM_41,
.hsync_gpio_num = GPIO_NUM_39,
.pclk_gpio_num = GPIO_NUM_0,
.disp_gpio_num = GPIO_NUM_38, // DISP/ENABLE
.num_fbs = 1,
.data_gpio_nums = {
// B0..B4
GPIO_NUM_8, GPIO_NUM_3, GPIO_NUM_46, GPIO_NUM_9, GPIO_NUM_1,
// G0..G5
GPIO_NUM_5, GPIO_NUM_6, GPIO_NUM_7, GPIO_NUM_15, GPIO_NUM_16, GPIO_NUM_4,
// R0..R4
GPIO_NUM_45, GPIO_NUM_48, GPIO_NUM_47, GPIO_NUM_21, GPIO_NUM_14
},
.bounce_buffer_size_px = 10 * 800,
.sram_trans_align = 64,
.psram_trans_align = 64,
.flags = {
.fb_in_psram = 1,
.disp_active_low = 0,
},
.timings = {
.pclk_hz = 15000000,
.h_res = 800,
.v_res = 480,
.hsync_front_porch = 210,
.hsync_pulse_width = 4,
.hsync_back_porch = 43,
.vsync_front_porch = 22,
.vsync_pulse_width = 4,
.vsync_back_porch = 12,
.flags = {
.pclk_active_neg = 1,
.pclk_idle_high = 0,
.de_idle_high = 0,
.hsync_idle_low = 0,
.vsync_idle_low = 0,
},
},
};
esp_lcd_panel_handle_t panel = NULL;
esp_err_t err = esp_lcd_new_rgb_panel(&cfg, &panel);
if (err != ESP_OK) return err;
if ((err = esp_lcd_panel_reset(panel)) != ESP_OK) return err;
if ((err = esp_lcd_panel_init(panel)) != ESP_OK) return err;
if ((err = esp_lcd_panel_disp_on_off(panel, true)) != ESP_OK) return err;
*out_panel = panel;
return ESP_OK;
}
f_lvgl_port.c:
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "esp_log.h"
#include "touch.h"
#include "lvgl_port.h"
#include "lvgl.h"
#include "esp_lcd_panel_ops.h"
#include "touch_calib.h"
static const char *TAG = "LVGL_PORT";
SemaphoreHandle_t xSemaphoreDisplay;
static esp_lcd_panel_handle_t s_panel = NULL;
static void lvgl_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) {
int x1 = area->x1;
int y1 = area->y1;
int x2 = area->x2 + 1;
int y2 = area->y2 + 1;
esp_lcd_panel_draw_bitmap(s_panel, x1, y1, x2, y2, color_p);
lv_disp_flush_ready(disp_drv);
}
static void lv_tick_task(void *arg) {
(void)arg;
lv_tick_inc(2);
}
void f_updateScreen(void *arg){
while (1) {
lock();
lv_timer_handler();
unlock();
vTaskDelay(pdMS_TO_TICKS(20));
}
}
static void lvgl_touch_read_cb(lv_indev_drv_t *indev_drv, lv_indev_data_t *data) {
(void)indev_drv;
if (touch_calib_is_calibrating()) {
data->state = LV_INDEV_STATE_REL;
return;
}
uint16_t rx, ry;
if (!touch_get_xy(&rx, &ry)) {
data->state = LV_INDEV_STATE_REL;
return;
}
int x = 0, y = 0;
if (!touch_calib_apply(rx, ry, &x, &y, 800, 480)) {
// Fallback (se ainda não calibrado) — você pode deixar REL pra evitar cliques errados:
// data->state = LV_INDEV_STATE_REL; return;
// ou manter um map bruto provisório:
x = 0; y = 0;
}
data->state = LV_INDEV_STATE_PR;
data->point.x = x;
data->point.y = y;
// Debug:
//printf("raw(%u,%u) -> px(%d,%d)\n", rx, ry, x, y);
}
void lvgl_port_init(esp_lcd_panel_handle_t panel) {
s_panel = panel;
lv_init();
// // 1) buffers do LVGL (recomendo INTERNAL+DMA)
// static lv_disp_draw_buf_t draw_buf;
// // Use um buffer relativamente pequeno; 800 * 40 pixels funciona muito bem.
// const int HOR = 800;
// const int BUF_LINES = 20; // quanto mais linhas, mais RAM usada mas menos chamadas de flush (e.g. 800*240 = full screen)
// static lv_color_t *buf1 = NULL;
// buf1 = heap_caps_malloc(HOR * BUF_LINES * sizeof(lv_color_t), MALLOC_CAP_DMA);
// // É um teste (pode dar problema ou ficar lento)
// //buf1 = heap_caps_malloc(HOR * BUF_LINES * sizeof(lv_color_t), MALLOC_CAP_SPIRAM);
// assert(buf1);
// lv_disp_draw_buf_init(&draw_buf, buf1, NULL, HOR * BUF_LINES);
// 1) buffers do LVGL (DMA)
static lv_disp_draw_buf_t draw_buf;
const int HOR = 800;
const int BUF_LINES = 20; // 20~40 costuma ser bom
const size_t buf_pixels = HOR * BUF_LINES;
static lv_color_t *buf1 = NULL;
static lv_color_t *buf2 = NULL;
buf1 = heap_caps_malloc(buf_pixels * sizeof(lv_color_t), MALLOC_CAP_DMA);
buf2 = heap_caps_malloc(buf_pixels * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1 && buf2);
lv_disp_draw_buf_init(&draw_buf, buf1, buf2, buf_pixels);
// 2) driver de display
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = 800;
disp_drv.ver_res = 480;
disp_drv.flush_cb = lvgl_flush_cb;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = lvgl_touch_read_cb;
lv_indev_drv_register(&indev_drv);
// 3) Tick 1ms via esp_timer
const esp_timer_create_args_t tick_args = {
.callback = &lv_tick_task,
.name = "lv_tick"
};
esp_timer_handle_t tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&tick_args, &tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(tick_timer, 2 * 1000));
xSemaphoreDisplay = xSemaphoreCreateBinary();
xSemaphoreGive(xSemaphoreDisplay);
//xTaskCreatePinnedToCoreWithCaps(f_updateScreen,"lvgl", 3200, NULL, tskIDLE_PRIORITY+4, NULL, 1, MALLOC_CAP_SPIRAM);
xTaskCreatePinnedToCore(f_updateScreen, "lvgl", 3200, NULL, tskIDLE_PRIORITY+4, NULL, 1);
xTaskCreatePinnedToCore(touch_init, "touch", 4096, NULL, tskIDLE_PRIORITY+1, NULL, 1);
ESP_LOGI(TAG, "LVGL init OK");
}
void lock(){if (xSemaphoreDisplay!=NULL){xSemaphoreTake(xSemaphoreDisplay, portMAX_DELAY);}}
void unlock(){if (xSemaphoreDisplay!=NULL){xSemaphoreGive(xSemaphoreDisplay);}}
The issue is that the display correctly shows the screen drawn in LVGL.
That in itself isn’t the problem.
The issue is that the screen flickers constantly.
I’ve already tried everything with the help of AI (ChatGPT) and I can’t fix this flickering screen problem.
Does anyone have any idea what might be happening?
