ESP-IDF移植lvgl 驱动 ST7789

news2024/11/20 14:41:10

文章目录

  • 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 == 8
    lv_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" #");
#else
    lv_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);
#endif
    lv_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
点击链接加入群聊【蜡笔小芯的嵌入式交流群】
![])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1593832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络——ARP协议

前言 本博客是博主用于复习计算机网络的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 这篇博客是在B站掌芝士zzs这个UP主的视频的总结&#xff0c;讲的非常好。 可以先去看一篇视频&#xff0c;再来参考这篇笔记&#xff08;或者说直接偷走&#xff09;。 …

Javaweb监听器(Listener)

一、概念 1.Listener表示监听器。是Javaweb三大组件&#xff08;Servlet、Filter、Listener&#xff09;之一 2.优先级为监听器>过滤器>servlet 3.监听器可以监听就是在application&#xff0c;session&#xff0c;request三个对象创建、销毁或者往其中添加修改删除属性…

MySQ数据库: MySQL数据库的安装配置 ,图文步骤详细,一篇即可完成安装完成! MySQL数据库如何与客户端连接

LiuJinTao&#xff1a; 2024年4月14日 文章目录 MySQL的安装配置1. 下载2. 安装 三、 MySQL 启动与停止1. 第一种 方式&#xff1a;2. 第二种方式&#xff1a; 四、MySQL 客户端连接2. 方式二&#xff1a; MySQL的安装配置 1. 下载 官方下载网址&#xff1a;https://www.mysq…

2024蓝桥杯省赛C++软件算法研究生组题解+游记

A题 给你一个音游的游戏记录log.txt&#xff0c;判断玩家的最高连击数 题解 水题&#xff0c;但是要小心&#xff0c;miss的键需要重置k0&#xff0c;超时但正确的键重置k1 个人答案是9 B题 计算1~2024041331404202中有多少个数x满足x! - x*(x1)/2能被100整除 题解 首先…

数字乡村创新实践探索农业现代化与乡村振兴新路径:科技赋能农村全面振兴与农民幸福新篇章

随着信息技术的飞速发展&#xff0c;数字乡村成为推动农业现代化与乡村振兴的重要战略举措。科技赋能下的数字乡村创新实践&#xff0c;不仅提升了农业生产的智能化水平&#xff0c;也为乡村治理和农民生活带来了翻天覆地的变化。本文旨在探讨数字乡村创新实践在农业现代化与乡…

【vue】Vue3开发中常用的VSCode插件

Vue - Official&#xff1a;vue的语法特性&#xff0c;如代码高亮&#xff0c;自动补全等 Vue VSCode Snippets&#xff1a;自定义一些代码片段 v3单文件组件vdata数据vmethod方法 别名路径跳转 参考 https://www.bilibili.com/video/BV1nV411Q7RX

Java+vue2+springboot智慧班牌系统源码,支持PC端、移动客户端、电子班牌端,SaaS模式部署

智慧班牌作为一个班级的标识&#xff0c;也是班级空间日常管理的载体&#xff0c;作为班级文化展示交流窗口与学科教学、德育管理&#xff0c;以及学校信息収布等有机结合起来&#xff0c;作为学生展示的平台&#xff0c;又可应用于普及教育安全知识和科学文化&#xff0c;拓展…

JVM复习

冯诺依曼模型与计算机处理数据过程相关联&#xff1a; 冯诺依曼模型&#xff1a; 输入/输出设备存储器输出设备运算器控制器处理过程&#xff1a; 提取阶段&#xff1a;输入设备传入原始数据&#xff0c;存储到存储器解码阶段&#xff1a;由CPU的指令集架构ISA将数值解…

斯坦福DeepMindGoogle提出SAFE:大模型长篇事实检验新标杆

关注公众号【AI论文解读】回复或者发送&#xff1a;论文解读 获取本文论文PDF 引言&#xff1a;大型语言模型的长篇事实性挑战 在当今信息爆炸的时代&#xff0c;大型语言模型&#xff08;LLMs&#xff09;在处理开放式话题的事实性问题时&#xff0c;常常会产生包含事实错…

【进阶六】Python实现SDVRPTW常见求解算法——自适应大邻域算法(ALNS)

基于python语言&#xff0c;采用经典自适应大邻域算法&#xff08;ALNS&#xff09;对 带硬时间窗的需求拆分车辆路径规划问题&#xff08;SDVRPTW&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整2.1 需求拆分2.2 需求拆分后的服务时长取值问题 3. 求解结果4…

基本的数据类型在16位、32位和64位机上所占的字节大小

1、目前常用的机器都是32位和64位的&#xff0c;但是有时候会考虑16位机。总结一下在三种位数下常用的数据类型所占的字节大小。 数据类型16位(byte)32位(byte)64位(byte)取值范围char111-128 ~ 127unsigned char1110 ~ 255short int / short222-32768~32767unsigned short222…

gitlab:Could not resolve host

fatal: unable to access http://xxx.git/: Could not resolve host: yyy Git-fatal: unable to access ‘https://gitlab.XX.git/‘: Could not resolve host: gitlab.XX.com.cn_drone unable to access .git/: could-CSDN博客 原因&#xff1a; 克隆的时候使用的是这里的HTT…

mysql题目5

tj11&#xff1a; select max(c.teacher_age) 最大的年龄 from tb_teacher c tj12: select a.class_name 班级名称,b.student_name 学生姓名,b.gender 学生性别 from tb_class a join tb_student b on a.class_idb.class_id join tb_teacher c on a.teacher_idc.teacher_id w…

复旦新出!大规模语言模型:从理论到实践,书籍PDF分享

自2018年以来&#xff0c;包含Google、OpenAI、Meta、百度、华为等公司和研究机构都纷纷发布了包括BERT&#xff0c; GPT等在内多种模型&#xff0c;并在几乎所有自然语言处理任务中都表现出色。 今天给大家推荐一本大模型方面的书籍<大规模语言模型&#xff1a;从理论到实…

Python学习笔记20 - 模块

什么叫模块 自定义模块 Python中的包 Python中常用的内置模块 第三方模块的安装与使用

虚拟机安装及拉取阿里云镜像

虚拟机安装及拉取阿里云镜像 1: 2: 3: 4: 5: 6: 7:这里设置为处理器核数的一半 8: 9: 10: 11: 12: 13: 14: 15: 16: 选好 光盘镜像文件后;点击关闭 按钮;然后选择完成 17: 18: 19: 20: 开始漫长的等待… 21: 点击完成配置,然后开始等待 22: 23: 24: 然后点击右下角的 完成配…

sc2024完善pay8001项目

1. 时间格式 package com.hong.entity;import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema;import java.math.BigDecimal; import java.util.Date; import javax.persistence.*;/*** 表名&#xff1a;t_pay* 表注释&…

分享一个预测模型web APP的功能模块和界面的设计

一个临床预测模型web APP功能模块与界面设计 随着医疗技术的不断进步&#xff0c;web APP是临床预测模型在医学领域的应用的重要形式。这里分享一个web APP的设计&#xff0c;手里有医学预测模型的可以尝试将其构建成webAPP&#xff0c;进而在临床实践中体验预测模型带来的便利…

Vitis HLS 学习笔记--优化循环启动间隔(II)

目录 1. 概述 2. 常规矩阵乘法 3. 数据依赖性和内存访问模式 4. 优化循环 5. 总结 1. 概述 Initiation Interval&#xff08;II&#xff09;定义为启动连续操作之间的时间间隔&#xff0c;以时钟周期为单位。低的II是高性能和高资源利用率的关键。 较高的II意味着在单位…

给你的AppImage创建桌面快捷方式

原文链接 https://www.cnblogs.com/HGNET/p/16396589.html 运行环境:Ubuntu 22.04 LTS 1.首先准备好AppImage文件并放在一个你知道的地方 2.打开终端&#xff0c;在/usr/share/applications下新建APP.desktop文件&#xff08;APP可以改成你的应用名称&#xff09; cd /usr/s…