1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 【esp32lvgl】-2.1 # esp32移植lvgl7驱动st7789屏幕(ESP-IDF框架)

【esp32lvgl】-2.1 # esp32移植lvgl7驱动st7789屏幕(ESP-IDF框架)

时间:2019-01-06 08:57:09

相关推荐

【esp32lvgl】-2.1 # esp32移植lvgl7驱动st7789屏幕(ESP-IDF框架)

目录

一、前言

二、代码

三、硬件说明

四、ESP-IDF设置(重要)

五、屏幕偏移修改驱动文件

参考资料

一、前言

前几天在ardiuno框架下基于platformIO用TFT_eSPI库实现了lvgl库的移植,这种方法虽然在lvgl的版本上有很大优势,但是platformIO的自定义库的添加有点麻烦,而且网上的大部分esp32资料都是基于ESP-IDF框架,因此还是在尝试一下ESP-IDF框架的lvgl开发。

esp32移植lvgl有官方的lvgl_port_esp32项目可以直接移植,不过目前的lvgl_port_esp32项目是基于lvgl7,主要是由于这个项目的重要组件lvgl_esp32_drivers库的lvgl8版本还没升级出来,但也没关系,作为一个初学者,版本的优劣可以先不考虑。下面将参考lvgl_port_esp32项目的内容简单实现一下lvgl7的移植,其中遇到了一些bug做一个记录。

二、代码

首先用ESP-IDF插件创建一个示例项目,并把lvgl_port_esp32项目内componets的lvgl和lvgl_esp32_drivers库复制到新建项目的componets内。

图一-示例文件树

然后把lvgl_port_esp32的main的内容复制到项目里,但是这里不用官方demo示例,自己添加一个简单的库做一个spinner效果测试一下添加自定义库的方法。这一步骤有四个文件的添加,参考了b站一位大佬的代码,即preloader.h,preloader.c,CMakeLists.txt(perloader库内),main.c。下面贴出来代码:

preloader.h

#ifndef _PRELOADER_H#define _PRELOADER_Hvoid create_preloader_demo();#endif

preloader.c

#include "preloader.h"#include "lvgl.h"void create_preloader_demo(){lv_obj_t * preload = lv_spinner_create(lv_scr_act(),NULL);lv_obj_set_size(preload,100,100);lv_obj_align(preload,NULL,LV_ALIGN_CENTER,0,0);}

CMakeLists.txt(perloader库内)

idf_component_register(SRCS "preloader.c"INCLUDE_DIRS "."REQUIRES lvgl)

main.c

/* LVGL Example project** Basic project to test LVGL on ESP32 based projects.** This example code is in the Public Domain (or CC0 licensed, at your option.)** Unless required by applicable law or agreed to in writing, this* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR* CONDITIONS OF ANY KIND, either express or implied.*/#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "esp_freertos_hooks.h"#include "freertos/semphr.h"#include "esp_system.h"#include "driver/gpio.h"/* Littlevgl specific */#ifdef LV_LVGL_H_INCLUDE_SIMPLE#include "lvgl.h"#else#include "lvgl/lvgl.h"#endif#include "lvgl_helpers.h"#include "preloader.h"/**********************DEFINES*********************/#define LV_TICK_PERIOD_MS 1/*********************** STATIC PROTOTYPES**********************/static void lv_tick_task(void *arg);static void guiTask(void *pvParameter);static void create_demo_application(void);/*********************** APPLICATION MAIN**********************/void app_main() {/* If you want to use a task to create the graphic, you NEED to create a Pinned task* Otherwise there can be problem such as memory corruption and so on.* NOTE: When not using Wi-Fi nor Bluetooth you can pin the guiTask to core 0 */xTaskCreatePinnedToCore(guiTask, "gui", 4096*2, NULL, 0, NULL, 1);}/* Creates a semaphore to handle concurrent call to lvgl stuff* If you wish to call *any* lvgl function from other threads/tasks* you should lock on the very same semaphore! */SemaphoreHandle_t xGuiSemaphore;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);/* Use double buffered when not working with monochrome displays */#ifndef CONFIG_LV_TFT_DISPLAY_MONOCHROMElv_color_t* buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);assert(buf2 != NULL);#elsestatic lv_color_t *buf2 = NULL;#endifstatic lv_disp_buf_t disp_buf;uint32_t size_in_px = DISP_BUF_SIZE;#if defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_IL3820 \|| defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_JD79653A \|| defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_UC8151D\|| defined CONFIG_LV_TFT_DISPLAY_CONTROLLER_SSD1306/* Actual size in pixels, not bytes. */size_in_px *= 8;#endif/* Initialize the working buffer depending on the selected display.* NOTE: buf2 == NULL when using monochrome displays. */lv_disp_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;/* When using a monochrome display we need to register the callbacks:* - rounder_cb* - set_px_cb */#ifdef CONFIG_LV_TFT_DISPLAY_MONOCHROMEdisp_drv.rounder_cb = disp_driver_rounder;disp_drv.set_px_cb = disp_driver_set_px;#endifdisp_drv.buffer = &disp_buf;lv_disp_drv_register(&disp_drv);/* Register an input device when enabled on the menuconfig */#if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONElv_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, LV_TICK_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_MONOCHROMEfree(buf2);#endifvTaskDelete(NULL);}static void create_demo_application(void){create_preloader_demo();}static void lv_tick_task(void *arg) {(void) arg;lv_tick_inc(LV_TICK_PERIOD_MS);}

其中,main文件就是lvgl_port_esp32的main的create_demo_application函数内容删除,并改成我们自己的create_preloader_demo函数。

三、硬件说明

开发板:ESP-WROOM-32

屏幕:中景园1.47寸lcd显示屏高清ips172x320 st7789驱动液晶屏

四、ESP-IDF设置(重要)

ESP-IDF设置是有个小坑的,这里先贴一下主要需要改的部分:

图二-ESP-IDF设置-LVGL configuration

图三-ESP-IDF设置-LVGL TFT Display controller

图四-ESP-IDF设置-Display Pin Assignments

这些设定大部分没什么值得说的,按照自己的情况修改即可。但是这个LVGL TFT Display controller的频率设定应该是有坑的,我的设备这里只能设定为80MHz,其他情况下都会全黑屏,什么都不显示。

五、屏幕偏移修改驱动文件

到上一步编译其实是已经能点亮屏幕并显示的,但是屏幕会出现偏移的现象,经过多方查找,找到了这个屏幕的偏移修改方法。

在lvgl_esp32_drivers库的lvgl_tft文件夹内找到st7789.c驱动文件。并对函数void st7789_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)进行修改增加两行:

offsety1+=34;offsety2+=34;

修改后的函数内容变为:

/* The ST7789 display controller can drive 320*240 displays, when using a 240*240* display there's a gap of 80px, we need to edit the coordinates to take into* account that gap, this is not necessary in all orientations. */void st7789_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map){uint8_t data[4] = {0};uint16_t offsetx1 = area->x1;uint16_t offsetx2 = area->x2;uint16_t offsety1 = area->y1;uint16_t offsety2 = area->y2;offsety1+=34;offsety2+=34;#if (CONFIG_LV_TFT_DISPLAY_OFFSETS)offsetx1 += CONFIG_LV_TFT_DISPLAY_X_OFFSET;offsetx2 += CONFIG_LV_TFT_DISPLAY_X_OFFSET;offsety1 += CONFIG_LV_TFT_DISPLAY_Y_OFFSET;offsety2 += CONFIG_LV_TFT_DISPLAY_Y_OFFSET;#elif (LV_HOR_RES_MAX == 240) && (LV_VER_RES_MAX == 240)#if (CONFIG_LV_DISPLAY_ORIENTATION_PORTRAIT)offsetx1 += 80;offsetx2 += 80;#elif (CONFIG_LV_DISPLAY_ORIENTATION_LANDSCAPE_INVERTED)offsety1 += 80;offsety2 += 80;#endif#endif/*Column addresses*/st7789_send_cmd(ST7789_CASET);data[0] = (offsetx1 >> 8) & 0xFF;data[1] = offsetx1 & 0xFF;data[2] = (offsetx2 >> 8) & 0xFF;data[3] = offsetx2 & 0xFF;st7789_send_data(data, 4);/*Page addresses*/st7789_send_cmd(ST7789_RASET);data[0] = (offsety1 >> 8) & 0xFF;data[1] = offsety1 & 0xFF;data[2] = (offsety2 >> 8) & 0xFF;data[3] = offsety2 & 0xFF;st7789_send_data(data, 4);/*Memory write*/st7789_send_cmd(ST7789_RAMWR);uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);st7789_send_color((void*)color_map, size * 2);}

自此,已经成功实现esp32移植lvgl7驱动st7789屏幕。

图五-运行效果

参考资料

ESP32 IDF LVGL 1.47寸圆角屏幕测试_史达芬林的博客-CSDN博客(屏幕设定)

ESP32 IDF 移植 LVGL - 哔哩哔哩 ()(代码主体)

【开源】中景园1.47寸圆角屏测试 IPS 172*320,PPI很高呀!_哔哩哔哩_bilibili(硬件来源)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。