ESP32驱动TFT-LCD开发记录(基于ESP-IDF)

写在前面

本文档为用ESP32做显示屏的一些技术上的总结,大家在阅读时可以根据自己的需要选择跳过一些不必要的内容。文档为个人总结,难免会有疏忽或错误,还希望大家直接在评论区指出,谢谢!
说明:整个模块的开发基于ESP32-NodeMCU开发板进行,开发环境是ESP-IDF+VScode,使用了FreeRTOS实时操作系统。

ESP-IDF开发环境配置

ESP-IDF 依赖工具

  1. 安装python

下载链接:https://www.python.org/downloads/
安装后需要配置pip环境
在 Linux 下:~/.pip/pip.conf
在 Windows 下:C:\Users\你的用户名\pip\pip.ini文件
[global] index-url = https://pypi.tuna.tsinghua.edu.cn/simple [install] trusted-host=pypi.tuna.tsinghua.edu.cn

  1. 安装Git:链接https://git-scm.com/downloads
  2. 安装 Microsoft C++ 生成工具

链接https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/

  1. 安装 Visual Studio Code:链接https://code.visualstudio.com/Download

搭建教程

安装好依赖工具和 vscode 之后,启动 vscode。
点击 Extensions(Ctrl + Shift + X),搜索插件 Espressif IDF,点击 install(安装)
安装好以后,按下F1 ,并找到 ESP-IDF: Configure ESP-IDF extension打开
在这里插入图片描述

download server(下载服务器) 选择 Espressif
ESP-IDF version(ESP-IDF 版本)选择最新的就好了
其他保持默认
Install
在这里插入图片描述

运行示例项目

按下F1,选择Show Examples Projects(如下图)
在这里插入图片描述
在这里插入图片描述
然后选择一个希望运行的项目,并创建它,把它保存在希望保存的文件夹里。
然后对例程进行编译:F1,Build your project
在这里插入图片描述
然后它会报错,说没有这些包,那你就执行它说的那个 install.bat,装完以后,重新build就可以了。
接下来,下载 CP210x 串口驱动(https://www.silabs.com/documents/public/software/CP210x_Universal_Windows_Driver.zip)。
在这里插入图片描述
让开发板进到下载模式(有自动下载功能的开发板可以忽略,其他芯片的下载模式网上可以搜到)
最后,下载程序,如下图
在这里插入图片描述

使用例程时某些需要解决的问题

1. GPIO_GET到的值无法改变

使用以下代码,LED无法正常取反

bool LED = (bool)gpio_get_level(LED_GPIO); 
gpio_set_level(LED_GPIO, !LED); 
//gpio_set_level(LED_GPIO, ~LED); 

目前还没有解决,如果有懂哥看到的话希望能够指导一下,谢谢!

2. 编译成功但是程序无法下载进去

解决方案:电机vscode左下方的清除,然后再下载即可
在这里插入图片描述

ESP32+显示屏硬件电路

这部分知识简单地放出硬件的接线,目的是让大家知道我的引脚连接方式(硬件的其他部分后面会持续更新)
在这里插入图片描述

LVGL显示屏方案

使用LVGL库的原因在于UI设计,写过嵌入式显示屏的小伙伴应该很清楚,平时写的显示屏基本上操作界面与产品都是差别非常大的,用来离线调参或者显示一些数据打比赛用还可以,但是距离产品的差距实在太大。但是如果自己手动去写嵌入式显示屏的库开发周期则太长,不仅在现阶段不太显示,而且即时写出来了也没有办法建立起技术壁垒,因此选择使用现有的库。
关于LVGL与其他常见嵌入式GUI的对比可以见开源轻量级显示框架LVGL简介 - 知乎 (zhihu.com)

LVGL的下载

要使用LVGL,就要先把它的库下载下来。下载LVGL的库需要到Github上,网址为https://github.com/lvgl
由于我们用的是ESP32,所以就下载对应的库即可。
在这里插入图片描述
这里我在下载的时候出现了一点小问题,如下图
在这里插入图片描述
Github里面放的两个文件是外部链接,而这两个文件又是我们必须下载的。如果熟悉Git的大佬,基本都会用在cmd里面直接共git clone把整个文件夹clone到本地,但是如果这么操作会发现这两个文件是空的,因此就需要分别进入上图所示两个链接,将其分别下载下来。
LVGL官网:https://lvgl.io/

LVGL的基本使用

将LVGL下载下来后,我们直接把components文件夹复制到我们之前建好的工程里面(或者放在例程里面),如下图
在这里插入图片描述
并需要修改两个CMakeLists文件和一个Makefile文件(只要稍微了解C语言编译就清楚这些文件是用来做什么的,这里不再赘述),分别如下:
\main\CMakeLists.txt:

set(SOURCES main.c )
idf_component_register(SRCS ${SOURCES}
                    INCLUDE_DIRS .
                    REQUIRES lvgl_esp32_drivers lvgl_touch lvgl_tft lvgl lv_examples)

target_compile_definitions(${COMPONENT_LIB} PRIVATE LV_CONF_INCLUDE_SIMPLE=1)

CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
list(APPEND EXTRA_COMPONENT_DIRS components/lvgl_esp32_drivers components/lvgl_esp32_drivers/lvgl_touch components/lvgl_esp32_drivers/lvgl_tft)

if (NOT DEFINED PROJECT_NAME)
    project(lvgl-demo)
endif (NOT DEFINED PROJECT_NAME)

Makefile:

PROJECT_NAME := lvgl-demo
EXTRA_COMPONENT_DIRS := components/lvgl_esp32_drivers/lvgl_tft components/lvgl_esp32_drivers/lvgl_touch
include $(IDF_PATH)/make/project.mk

然后clean,在编译就可以了。
入门LVGL并不算是非常困难,基本上跟着官方的例程大概写写就能清楚基本的使用方法。
打开上述下载下来的文件夹,打开到如下图中src文件夹中,里面的文件夹即为官方例程,跟着注释学习即可快速入门。
在这里插入图片描述
最后再安利一个LVGL的教程:什么是Lvgl? — 百问网LVGL中文教程手册文档 1.0 文档 (100ask.net)
韦东山写的,其实就是翻译了英文的教程,但使用环境是Code::Blocks的LVGL模拟器。

应用LVGL显示各种控件(待更新)

串口

串口这部分主要是用来与控制电机的MCU进行通讯用的,以下是串口配置和收发的代码,主要也是起备忘作用,大家阅读的时候可以跳过。
串口配置:

void uart_init(void)
{
    esp_log_level_set(TAG, ESP_LOG_INFO);

    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
    uart_param_config(EX_UART_NUM, &uart_config);

    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(EX_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //Set uart pattern detect function.
    uart_enable_pattern_det_baud_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0);
    //Reset the pattern queue length to record at most 20 pattern positions.
    uart_pattern_queue_reset(EX_UART_NUM, 20);
}

串口发送:

static void tx_task(void *arg)
{
    int len_melloc = 9;
    uint8_t * tx_buf = (uint8_t *)malloc(len_melloc);
    *tx_buf     = 0x31; // 头
    *(tx_buf+1) = 0x07;
    *(tx_buf+2) = 0x02;
    *(tx_buf+3) = 0x00;
    *(tx_buf+4) = 0x00;
    *(tx_buf+5) = 0x00;
    *(tx_buf+6) = 0x00;
    *(tx_buf+7) = 0x00; // 校验
    *(tx_buf+8) = 0xaa; // 尾
    // 求和校验
    for(int i = 1; i <= 6; i++)
    {
        *(tx_buf+7) += *(tx_buf + i);
    }
    // esp_log_level_set(UART_TASK_TAG, ESP_LOG_INFO);
    while (1) {  
        uart_write_bytes(UART_NUM_0, (const char *)tx_buf, len_melloc);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

串口接收:

static void uart_event_task(void *pvParameters)
{
    uart_event_t event;
    size_t buffered_size;
    uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
    for(;;) {
        //Waiting for UART event.
        if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
            bzero(dtmp, RD_BUF_SIZE);
            // ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
            if(event.type == UART_DATA) {
                //Event of UART receving data
                uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
                if(*dtmp == 0x31 && *(dtmp + 8) == 0xaa)
                {
                    uint8_t* dtmp_check = (uint8_t*) malloc(1);
                    *dtmp_check = 0x00;
                    for(int i = 1; i <= 6; i++)
                    {
                        *dtmp_check += *(dtmp + i);
                    }
                    if(*dtmp_check == *(dtmp + 7))
                    {
                        uart_write_bytes(EX_UART_NUM, (const char*)dtmp, 9);
                    }
                }
                break;
            }
        }
    }
    free(dtmp);
    dtmp = NULL;
    vTaskDelete(NULL);
}

WiFi无线连接(STA)

WiFi连接一般来说有两种模式,AP和STA。
简单来说,AP模式是将ESP32作为路由器,STA模式是将ESP32作为无线网络的终端(可以连接到其他的WiFi)。
我们采用的是STA的方式,通过连接到用户家里或者其他地方的WiFi,来实现数据的传输与通讯。
(具体实现方式后续更新)

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值