ESP-IDF移植lvgl 驱动 ST7789

2024-04-14 06:04
文章标签 驱动 移植 lvgl idf esp st7789

本文主要是介绍ESP-IDF移植lvgl 驱动 ST7789,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1 前言
  • 2 准备
  • 3 移植LVGL
    • 3.1 工程准备
    • 3.2 修改 CMakeLists.txt文件编译 LVGL
    • 3.3 编译LVGL
  • 4 编译 ST7789 LCD驱动
  • 5 发现问题

1 前言

本教程开始学习 LVGL的,开始之前要把环境配置好,首先就需要移植 lvgl,使用的是 esp32 环境,使用的 LCD驱动IC是 ST7789,没有使用到触摸屏。

2 准备

组件下载地址

https://components.espressif.com/
  • 准备一个空的工程

  • 下载 esp_lvgl_port

    https://components.espressif.com/components/espressif/esp_lvgl_port
    
  • 下载 LVGL8.3.6

    https://components.espressif.com/components/lvgl/lvgl/versions/8.3.6~1?language=en
    

    下载位置

    在这里插入图片描述

这里说明一下:为什么使用手动下载,很多教程都是使用的是 idf_component.yml 这个文件进行配置,但是在下载 esp_lvgl_port 的时候,会自动下载 LVGL 8 的最新版,或者LVGL 9 的最新版,而且弄好以后,还需要重新吧远程的文件重新移动到本地文件,不然后面修改组件的代码,会编译报错。笔者想使用的是 LVGL 8.3.6,所以选择手动下载配置,

3 移植LVGL

3.1 工程准备

  • components 文件夹

main 文件夹 同级别 的目录下,新建一个 components 的文件夹,把刚刚下载好的两个文件移动到 components 目录下,并修改一个简单的文件夹名字,

在这里插入图片描述

3.2 修改 CMakeLists.txt文件编译 LVGL

esp_lvgl_Port 依赖于 LVGL,修改 esp_lvgl_Port -> CMakeLists.txt 文件

`lvgl_lvgl`改成 `lvgl``lvgl_lvgl`改成 "lvgl的文件夹名字"

在这里插入图片描述

3.3 编译LVGL

  • 编译成功

在这里插入图片描述

4 编译 ST7789 LCD驱动

在下载 esp_lvgl_Port 的时候,就会自动下载了 ST7789的驱动,如果不是 ST7789的驱动,那么需要自己去下载相关的驱动,下载地址也是

https://components.espressif.com/

搜索自己的 LCD驱动 IC 名称进行下载,放在 components 目录下即可。

  • main.c编写驱动代码
/** SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD** SPDX-License-Identifier: Apache-2.0*/#include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include "driver/i2c.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lvgl_port.h"/* LCD size */
#define EXAMPLE_LCD_H_RES   (320)
#define EXAMPLE_LCD_V_RES   (240)/* LCD settings */
#define EXAMPLE_LCD_SPI_NUM         (SPI3_HOST)
#define EXAMPLE_LCD_PIXEL_CLK_HZ    (40 * 1000 * 1000)
#define EXAMPLE_LCD_CMD_BITS        (8)
#define EXAMPLE_LCD_PARAM_BITS      (8)
#define EXAMPLE_LCD_COLOR_SPACE     (ESP_LCD_COLOR_SPACE_BGR)
#define EXAMPLE_LCD_BITS_PER_PIXEL  (16)
#define EXAMPLE_LCD_DRAW_BUFF_DOUBLE (1)
#define EXAMPLE_LCD_DRAW_BUFF_HEIGHT (50)
#define EXAMPLE_LCD_BL_ON_LEVEL     (1)/* LCD pins */
#define EXAMPLE_LCD_GPIO_SCLK       (GPIO_NUM_7)
#define EXAMPLE_LCD_GPIO_MOSI       (GPIO_NUM_6)
#define EXAMPLE_LCD_GPIO_RST        (GPIO_NUM_48)
#define EXAMPLE_LCD_GPIO_DC         (GPIO_NUM_4)
#define EXAMPLE_LCD_GPIO_CS         (GPIO_NUM_5)
#define EXAMPLE_LCD_GPIO_BL         (GPIO_NUM_45)static const char *TAG = "EXAMPLE";/* LCD IO and panel */
static esp_lcd_panel_io_handle_t lcd_io = NULL;
static esp_lcd_panel_handle_t lcd_panel = NULL;/* LVGL display and touch */
static lv_display_t *lvgl_disp = NULL;static esp_err_t app_lcd_init(void)
{esp_err_t ret = ESP_OK;/* LCD backlight */gpio_config_t bk_gpio_config = {.mode = GPIO_MODE_OUTPUT,.pin_bit_mask = 1ULL << EXAMPLE_LCD_GPIO_BL};ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));/* LCD initialization */ESP_LOGD(TAG, "Initialize SPI bus");const spi_bus_config_t buscfg = {.sclk_io_num = EXAMPLE_LCD_GPIO_SCLK,.mosi_io_num = EXAMPLE_LCD_GPIO_MOSI,.miso_io_num = GPIO_NUM_NC,.quadwp_io_num = GPIO_NUM_NC,.quadhd_io_num = GPIO_NUM_NC,.max_transfer_sz = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_DRAW_BUFF_HEIGHT * sizeof(uint16_t),};ESP_RETURN_ON_ERROR(spi_bus_initialize(EXAMPLE_LCD_SPI_NUM, &buscfg, SPI_DMA_CH_AUTO), TAG, "SPI init failed");ESP_LOGD(TAG, "Install panel IO");const esp_lcd_panel_io_spi_config_t io_config = {.dc_gpio_num = EXAMPLE_LCD_GPIO_DC,.cs_gpio_num = EXAMPLE_LCD_GPIO_CS,.pclk_hz = EXAMPLE_LCD_PIXEL_CLK_HZ,.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,.spi_mode = 0,.trans_queue_depth = 10,};ESP_GOTO_ON_ERROR(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)EXAMPLE_LCD_SPI_NUM, &io_config, &lcd_io), err, TAG, "New panel IO failed");ESP_LOGD(TAG, "Install LCD driver");const esp_lcd_panel_dev_config_t panel_config = {.reset_gpio_num = EXAMPLE_LCD_GPIO_RST,.color_space = EXAMPLE_LCD_COLOR_SPACE,.bits_per_pixel = EXAMPLE_LCD_BITS_PER_PIXEL,};ESP_GOTO_ON_ERROR(esp_lcd_new_panel_st7789(lcd_io, &panel_config, &lcd_panel), err, TAG, "New panel failed");esp_lcd_panel_reset(lcd_panel);esp_lcd_panel_init(lcd_panel);esp_lcd_panel_mirror(lcd_panel, true, true);esp_lcd_panel_disp_on_off(lcd_panel, true);/* LCD backlight on */ESP_ERROR_CHECK(gpio_set_level(EXAMPLE_LCD_GPIO_BL, EXAMPLE_LCD_BL_ON_LEVEL));return ret;err:if (lcd_panel) {esp_lcd_panel_del(lcd_panel);}if (lcd_io) {esp_lcd_panel_io_del(lcd_io);}spi_bus_free(EXAMPLE_LCD_SPI_NUM);return ret;
}static esp_err_t app_lvgl_init(void)
{/* Initialize LVGL */const lvgl_port_cfg_t lvgl_cfg = {.task_priority = 4,         /* LVGL task priority */.task_stack = 4096,         /* LVGL task stack size */.task_affinity = -1,        /* LVGL task pinned to core (-1 is no affinity) */.task_max_sleep_ms = 500,   /* Maximum sleep in LVGL task */.timer_period_ms = 5        /* LVGL timer tick period in ms */};ESP_RETURN_ON_ERROR(lvgl_port_init(&lvgl_cfg), TAG, "LVGL port initialization failed");/* Add LCD screen */ESP_LOGD(TAG, "Add LCD screen");const lvgl_port_display_cfg_t disp_cfg = {.io_handle = lcd_io,.panel_handle = lcd_panel,.buffer_size = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_DRAW_BUFF_HEIGHT * sizeof(uint16_t),.double_buffer = EXAMPLE_LCD_DRAW_BUFF_DOUBLE,.hres = EXAMPLE_LCD_H_RES,.vres = EXAMPLE_LCD_V_RES,.monochrome = false,/* Rotation values must be same as used in esp_lcd for initial settings of the screen */.rotation = {.swap_xy = false,.mirror_x = true,.mirror_y = true,},.flags = {.buff_dma = true,.swap_bytes = true,}};lvgl_disp = lvgl_port_add_disp(&disp_cfg);return ESP_OK;
}static void _app_button_cb(lv_event_t *e)
{lv_disp_rotation_t rotation = lv_disp_get_rotation(lvgl_disp);rotation++;if (rotation > LV_DISPLAY_ROTATION_270) {rotation = LV_DISPLAY_ROTATION_0;}/* LCD HW rotation */lv_disp_set_rotation(lvgl_disp, rotation);
}static void app_main_display(void)
{lv_obj_t *scr = lv_scr_act();/* Task lock */lvgl_port_lock(0);/* Your LVGL objects code here .... *//* Label */lv_obj_t *label = lv_label_create(scr);lv_obj_set_width(label, EXAMPLE_LCD_H_RES);lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, 0);
#if LVGL_VERSION_MAJOR == 8lv_label_set_recolor(label, true);lv_label_set_text(label, "#FF0000 "LV_SYMBOL_BELL" Hello world Espressif and LVGL "LV_SYMBOL_BELL"#\n#FF9400 "LV_SYMBOL_WARNING" For simplier initialization, use BSP "LV_SYMBOL_WARNING" #");
#elselv_label_set_text(label, LV_SYMBOL_BELL" Hello world Espressif and LVGL "LV_SYMBOL_BELL"\n "LV_SYMBOL_WARNING" For simplier initialization, use BSP "LV_SYMBOL_WARNING);
#endiflv_obj_align(label, LV_ALIGN_CENTER, 0, -30);/* Button */lv_obj_t *btn = lv_btn_create(scr);label = lv_label_create(btn);lv_label_set_text_static(label, "Rotate screen");lv_obj_align(btn, LV_ALIGN_BOTTOM_MID, 0, -30);lv_obj_add_event_cb(btn, _app_button_cb, LV_EVENT_CLICKED, NULL);/* Task unlock */lvgl_port_unlock();
}void app_main(void)
{/* LCD HW initialization */ESP_ERROR_CHECK(app_lcd_init());/* LVGL initialization */ESP_ERROR_CHECK(app_lvgl_init());/* Show LVGL objects */app_main_display();
}

5 发现问题

  • 发现是花屏,需要进入开启 Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI).

    在这里插入图片描述

  • 发现 颜色是反的, app_lcd_init 添加代码

    esp_lcd_panel_invert_color(lcd_panel, true);
    
  • 发现显示屏错位了,Y坐标 起点是 -80 并不是0,app_lcd_init 添加代码

     esp_lcd_panel_set_gap(lcd_panel, 0, 80);
    

文章是自己总结而记录,有些知识点没说明白的,请各位看官多多提意见,多多交流,欢迎大家留言
如果技术交流可以加以下群,方便沟通
QQ群:370278903
点击链接加入群聊【蜡笔小芯的嵌入式交流群】
![])

这篇关于ESP-IDF移植lvgl 驱动 ST7789的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/902256

相关文章

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

电脑驱动分类

电脑驱动程序(驱动程序)是操作系统与硬件设备之间的桥梁,用于使操作系统能够识别并与硬件设备进行通信。以下是常见的驱动分类: 1. 设备驱动程序 显示驱动程序:控制显卡和显示器的显示功能,负责图形渲染和屏幕显示。 示例:NVIDIA、AMD 显示驱动程序。打印机驱动程序:允许操作系统与打印机通信,控制打印任务。 示例:HP、Canon 打印机驱动程序。声卡驱动程序:管理音频输入和输出,与声卡硬件

RT-Thread(Nano版本)的快速移植(基于NUCLEO-F446RE)

目录 概述 1 RT-Thread 1.1 RT-Thread的版本  1.2 认识Nano版本 2 STM32F446U上移植RT-Thread  2.1 STM32Cube创建工程 2.2 移植RT-Thread 2.2.1 安装RT-Thread Packet  2.2.2 加载RT-Thread 2.2.3 匹配相关接口 2.2.3.1 初次编译代码  2.2.3.

WIN11 ESP32 IDF + VSCODE 环境搭建[教程向]

前言 目录 前言 安装ESP32-IDF VSCODE插件安装 编译测试 很多时候我们想学习一门新的技能,需要使用全新的开发环境,很多时候我们会在安装环境这个环节卡住很久,这里简单介绍一下ESP32+VSCODE环境搭建。 安装ESP32-IDF https://dl.espressif.cn/dl/esp-idf/?idf=4.4 直接复制上面链接,进入idf下载界面。

麒麟系统安装GPU驱动

1.nvidia 1.1显卡驱动 本机显卡型号:nvidia rtx 3090 1.1.1下载驱动 打开 https://www.nvidia.cn/geforce/drivers/ 也可以直接使用下面这个地址下载 https://www.nvidia.com/download/driverResults.aspx/205464/en-us/ 1.1.3安装驱动 右击,

龙芯+FreeRTOS+LVGL实战笔记(新)——05部署主按钮

本专栏是笔者另一个专栏《龙芯+RT-Thread+LVGL实战笔记》的姊妹篇,主要的区别在于实时操作系统的不同,章节的安排和任务的推进保持一致,并对源码做了改进和优化,各位可以先到本人主页下去浏览另一专栏的博客列表(目前已撰写36篇,图1所示),再决定是否订阅。此外,也可以前往本人在B站的视频合集(图2所示)观看所有演示视频,合集首个视频链接为: 借助RT-Thread和LVGL