微雪2.8寸触摸屏开发板开发日志(ESP-IDF 5.3)(更新中)

 

 

        偶然逛淘宝发现这块做工不错的板子,想着买来做LVGL移植开发。板子的外围设备也挺多:触摸屏,陀螺仪,microSD卡槽,扬声器接口(送扬声器),RTC时钟电池接口,电池接口,引出了I2C UART接口,主控是ESP32-S3(8M PSRAM,16M FLASH),运行LVGL也很流畅。

        这里是微雪的参考链接ESP32-S3-Touch-LCD-2.8

一.点亮LCD屏幕

        总所周知,带屏幕的开发板第一步当然是点亮屏幕啦(有现象才有动力!)。

        微雪的这块开发板的屏幕驱动芯片为ST7789T3,兼容ST7789系列芯片的驱动程序。所以可以直接CV拿来用。

        我这里也分享一下我的代码(写得很烂,参考一下就好了)

 LCD.c

#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/spi_master.h"
#include "esp_lcd_panel_io.h"
#include "LCD.h"
#include "driver/gptimer.h"

uint8_t LCD_TEMP[LCD_WIDTH * LCD_HIGH * 2];

//LCD操作句柄
esp_lcd_panel_io_handle_t lcd_io_handle;


void LCD_Init(void)
{
    char TAG[] = "LCD_Init";

    //创建spi总线
    spi_bus_config_t buscfg = {
        .sclk_io_num = LCD_SCL,
        .mosi_io_num = LCD_SDA,
        .miso_io_num = -1,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .flags = SPICOMMON_BUSFLAG_MASTER,
        .max_transfer_sz = LCD_WIDTH * 40 * sizeof(uint16_t),
    };
    ESP_LOGI(TAG,"初始化SPI");
    ESP_ERROR_CHECK(spi_bus_initialize(LCD_HOST, &buscfg, SPI_DMA_CH_AUTO));

    //初始化背光接口
    gpio_config_t blk_gpio_cfg = 
    {
        .pull_up_en = GPIO_PULLUP_DISABLE,      //禁用上拉
        .pull_down_en = GPIO_PULLDOWN_DISABLE,  //禁用下拉
        .mode = GPIO_MODE_OUTPUT,               //输出模式
        .intr_type = GPIO_INTR_DISABLE,         //禁用中断
        .pin_bit_mask = 1ULL <<LCD_BLK,                //设置GPIO
    };
    ESP_LOGI(TAG,"初始化背光接口");
    gpio_config(&blk_gpio_cfg);
    gpio_set_level(LCD_BLK, 0);

    //初始化复位接口
    gpio_config_t res_gpio_cfg = 
    {
        .pull_up_en = GPIO_PULLUP_DISABLE,      //禁用上拉
        .pull_down_en = GPIO_PULLDOWN_DISABLE,  //禁用下拉
        .mode = GPIO_MODE_OUTPUT,               //输出模式
        .intr_type = GPIO_INTR_DISABLE,         //禁用中断
        .pin_bit_mask = 1ULL << LCD_RES                 //设置GPIO
    };
    ESP_LOGI(TAG,"初始化复位接口");
    gpio_config(&res_gpio_cfg);

    esp_lcd_panel_io_spi_config_t io_config = 
    {
        .dc_gpio_num = LCD_DC,      //DC引脚,低:命令,高:数据
        .cs_gpio_num = LCD_CS,      //CS引脚
        .pclk_hz = 80000000,         //SPI时钟频率
        .lcd_cmd_bits = 8,          //命令长度
        .lcd_param_bits = 8,        //参数长度
        .spi_mode = 3,              //SPI模式
        .trans_queue_depth = 10,    //传输事务的队列深度
        .on_color_trans_done = NULL,//刷新完成回调函数
        .user_ctx = NULL,
        .flags = {
            .sio_mode = 0,
        },
    };
    ESP_LOGI(TAG,"初始化LCD");
    ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_HOST, &io_config, &lcd_io_handle));

    //硬件复位
    if(LCD_RES > 0)
    {
        ESP_LOGI(TAG,"硬件复位");
        gpio_set_level(LCD_RES, 0);
        vTaskDelay(pdMS_TO_TICKS(20));
        gpio_set_level(LCD_RES, 1);
        vTaskDelay(pdMS_TO_TICKS(20));
    }

    ESP_LOGI(TAG,"ST7789初始化");
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_SWREST, NULL, 0);//软件复位
    vTaskDelay(pdMS_TO_TICKS(150));
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_SLPOUT, NULL, 0);//退出休眠模式
    vTaskDelay(pdMS_TO_TICKS(200));
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_COLMOD, (uint8_t[]){0x05}, 1);//选择RGB模式
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_RAMCTRL, (uint8_t[]){0x00, 0xF0}, 2);
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_INVON, NULL, 0);//颜色翻转
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_NORON, NULL, 0);//普通显示模式
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_MADCTL, (uint8_t[]){0x00}, 1);//屏幕旋转方向,0x00:不旋转,0x60:顺时针90度,0xC0:180度,0xA0:顺时针270度
    vTaskDelay(pdMS_TO_TICKS(150));
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_DISPON, NULL, 0);
    vTaskDelay(pdMS_TO_TICKS(300));

    gpio_set_level(LCD_BLK, 1);//开启背光
}

void LCD_Write(uint16_t X, uint16_t Y, uint16_t Width, uint16_t High, void* Data)
{
    char TAG[] = "LCD_Write";
    // ESP_LOGI(TAG,"定位显示区域");
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_CASET, (uint8_t[]){(X >> 8) & 0xFF, X & 0xFF, ((X + Width - 1) >> 8) & 0xFF, (X + Width - 1) & 0xFF}, 4);
    esp_lcd_panel_io_tx_param(lcd_io_handle, LCD_CMD_RASET, (uint8_t[]){(Y >> 8) & 0xFF, Y & 0xFF, ((Y + High - 1) >> 8) & 0xFF, (Y + High - 1) & 0xFF}, 4);
    size_t len = Width * High * 2;
    // ESP_LOGI(TAG,"发送数据");
    esp_lcd_panel_io_tx_color(lcd_io_handle, LCD_CMD_RAMWR, Data, len);
}

uint16_t LCD_RGB(uint8_t R, uint8_t G, uint8_t B)
{
    return 0x0000 | (R / 8) << 11 | (G / 4) << 5 | (B / 8);
}

void LCD_Clear(uint16_t color)
{
    uint8_t color_temp = color >> 8;
    for(uint32_t i = 0; i < (LCD_WIDTH * LCD_HIGH * 2); i++)
    {
        LCD_TEMP[i++] = color_temp;
        LCD_TEMP[i] = color;
    }
    LCD_Write(0, 0, LCD_WIDTH, LCD_HIGH, LCD_TEMP);
}

void LCD_ShowImg(uint16_t X, uint16_t Y, uint16_t Width, uint16_t High, uint8_t* Img)
{
    for(uint32_t i = 0; i < Width * High; i++)
    {
        LCD_TEMP[((Y + i / Width) * LCD_WIDTH + X + i % Width) * 2] = Img[i * 2];
        LCD_TEMP[((Y + i / Width) * LCD_WIDTH + X + i % Width) * 2 + 1] = Img[i * 2 + 1];
    }
    LCD_Write(0, 0, LCD_WIDTH, LCD_HIGH, LCD_TEMP);
}

LCD.h

#ifndef __LCD_H
#define __LCD_H


#define LCD_SCL 40
#define LCD_SDA 45
#define LCD_RES 39
#define LCD_DC  41
#define LCD_CS  42
#define LCD_BLK 5
#define LCD_WIDTH   240
#define LCD_HIGH    320

#define LCD_HOST    SPI2_HOST

#define LCD_CMD_SWREST  0x01
#define LCD_CMD_SLPOUT  0x11
#define LCD_CMD_COLMOD  0x3A
#define LCD_CMD_RAMCTRL 0xB0
#define LCD_CMD_INVON   0x21
#define LCD_CMD_NORON   0x13
#define LCD_CMD_MADCTL  0x36
#define LCD_CMD_DISPON  0x29
#define LCD_CMD_CASET   0x2A
#define LCD_CMD_RASET   0x2B
#define LCD_CMD_RAMWR   0x2C


void LCD_Init(void);
void LCD_Write(uint16_t X, uint16_t Y, uint16_t Width, uint16_t High, void* Data);
uint16_t LCD_RGB(uint8_t R, uint8_t G, uint8_t B);
void LCD_Clear(uint16_t color);
void LCD_ShowImg(uint16_t X, uint16_t Y, uint16_t Width, uint16_t High, uint8_t* Img);

#endif

        经过测试显示纯色和rgb565的图片都没问题(idf版本为5.3),有问题的话还望大佬指正。

二.获取触摸数据

        通过开发板资料得知,这块板子的触摸芯片为CST328,但是用这个驱动芯片的屏幕比较少,几乎只能参考手册,这里我参考了这位博主的文章用ESP32S3驱动CST328并在lvgl_esp32_drivers新增芯片 | 过程记录过程还是比较详细,但是idf的版本为4.4.8,我这里做了5.3的移植,大家可以参考一下(有问题的话,还望大佬指正)

CST328.c

#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"

#include "CST328.h"

CST328_Data_Struct CST328_Data;

//i2c总线控制句柄
i2c_master_bus_handle_t bus_handle;

//i2c从机控制句柄
i2c_master_dev_handle_t cst328_handle;

//CST硬件初始化
void CST328_RST(void)
{
    vTaskDelay(pdMS_TO_TICKS(50));

    //端口初始化
    gpio_set_direction(TP_INT, GPIO_MODE_OUTPUT_OD);
    gpio_set_direction(TP_RST, GPIO_MODE_OUTPUT);
    gpio_set_level(TP_INT, 1);
    gpio_set_level(TP_RST, 1);

    vTaskDelay(pdMS_TO_TICKS(50));
    gpio_set_level(TP_RST, 0);
    vTaskDelay(pdMS_TO_TICKS(5));
    gpio_set_level(TP_RST, 1);
    vTaskDelay(pdMS_TO_TICKS(200));
    gpio_set_level(TP_INT, 0);
}

//CST328初始化
void CST328_I2C_Init(void)
{
    //I2C主机总线cfg
    i2c_master_bus_config_t i2c_mst_config = {
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .i2c_port = -1,
        .scl_io_num = TP_SCL,
        .sda_io_num = TP_SDA,
        .glitch_ignore_cnt = 7,
        .flags.enable_internal_pullup = true,
    };

    //注册I2C主机总线
    ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));

    //i2c从机cfg
    i2c_device_config_t dev_cfg = {
        .dev_addr_length = I2C_ADDR_BIT_LEN_7,
        .device_address = CST328_ADDRESS >> 1,
        .scl_speed_hz = 1000000,
        .flags.disable_ack_check = false,
    };
    
    //注册从机设备
    ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &cst328_handle));
}

//CST328发送数据
esp_err_t CST328_SendData(uint8_t* Data, size_t Len)
{
    return i2c_master_transmit(cst328_handle, Data, Len, -1);
}

//CST328读取数据
esp_err_t CST328_ReceiveData(uint8_t* Buffer, size_t Len)
{
    return i2c_master_receive(cst328_handle, Buffer, Len, -1);
}

//CST328初始化
esp_err_t CST328_Init(void)
{
    char* TAG = "CST328_Init";
    esp_err_t ert;

    //初始化I2C
    ESP_LOGI(TAG, "初始化I2C");
    CST328_I2C_Init();

    //硬件初始化
    ESP_LOGI(TAG, "硬件初始化");
    CST328_RST();

    //软件初始化
    ESP_LOGI(TAG, "软件初始化");
    //进入ENUM_MODE_DEBUG_INFO模式
    if((ert = CST328_SendData((uint8_t[]){0xD1, 0x01}, 2) != ESP_OK))
    {
        ESP_LOGE(TAG, "I2C发送失败:%s", esp_err_to_name(ert));
        return ESP_FAIL;
    }
    //获取校码
    ESP_LOGI(TAG, "获取校码");
    CST328_SendData((uint8_t[]){0xD1, 0xFC}, 2);
    uint8_t Buffer[4] = {0x00};
    CST328_ReceiveData(Buffer, 4);
    //切换回默认模式
    CST328_SendData((uint8_t[]){0xD1, 0x09}, 2);
    uint16_t Check = ((uint16_t)Buffer[3] << 8) | Buffer[2];
    if(Check == 0xCACA)
    {
        ESP_LOGI(TAG, "校验码正确");
        return ESP_OK;
    } 
    else
    {
        ESP_LOGE(TAG, "校验码错误:0x%X%X", Buffer[3], Buffer[2]);
        return ESP_FAIL;
    }
}

//CST328读取数据
esp_err_t CST328_Read(void)
{
    uint8_t Buffer[4] = {0x00};

    //读取手指数量
    CST328_SendData((uint8_t[]){0xD0, 0x05}, 2);
    CST328_ReceiveData(Buffer, 1);
    if((Buffer[0] & 0x0F) != 1)
    {
        CST328_Data.State = 0;
        CST328_Data.X = 0;
        CST328_Data.Y = 0;
        CST328_Data.Pressure = 0;
        return ESP_FAIL;
    }
    //读取手指状态
    CST328_SendData((uint8_t[]){0xD0, 0x00}, 2);
    CST328_ReceiveData(Buffer, 1);
    if((Buffer[0] & 0x0F) == 0x06)
        CST328_Data.State = 1;
    else
        CST328_Data.State = 0;
    //读取手指坐标和压力值
    for(uint8_t i = 0; i < 4; i++)
    {
        CST328_SendData((uint8_t[]){0xD0, 0x01+i}, 2);
        CST328_ReceiveData(Buffer+i, 1);
    }
    CST328_Data.X = ((uint16_t)Buffer[0] << 4) | ((Buffer[2] & 0xF0) >> 4);
    CST328_Data.Y = ((uint16_t)Buffer[1] << 4) | (Buffer[2] & 0x0F);
    CST328_Data.Pressure = Buffer[3];
    return ESP_OK;
}

CST328.h

#ifndef __CST328_H__
#define __CST328_H__

#define TP_SCL  3
#define TP_SDA  1
#define TP_RST  2
#define TP_INT  4

#define CST328_ADDRESS 0x34
typedef struct CST328_Data_struct
{
    bool State;//手指状态(按下/抬起)
    uint16_t X;//X轴坐标
    uint16_t Y;//Y轴坐标
    uint8_t Pressure;//手指压力
}CST328_Data_Struct;

extern CST328_Data_Struct CST328_Data;

esp_err_t CST328_Init(void);
void CST328_RST(void);
void CST328_I2C_Init(void);
esp_err_t CST328_SendData(uint8_t* Data, size_t Len);
esp_err_t CST328_ReceiveData(uint8_t* Buffer, size_t Len);
esp_err_t CST328_Read(void);


#endif

main.c(测试)

#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "CST328.h"

void app_main(void)
{
    CST328_Init();
    while(1)
    {
        CST328_Read();
        if(CST328_Data.State)
            printf("X:%d    Y:%d    P:%d\n", CST328_Data.X, CST328_Data.Y, CST328_Data.Pressure);
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

 

 测试结果

 

### 关于Arduino微雪ESP32-S3开发板 #### 开发板特性概述 ESP32-S3 UNO是一款功能强大的开发板,具备双核处理器、16MB闪存、8MB PSRAM以及Wi-Fi和蓝牙5.0连接能力。该款开发板拥有丰富的外设接口资源,包括多达36个GPIO引脚,这使得它非常适合用于各种物联网项目和其他复杂应用的原型设计[^1]。 #### 使用TFT_eSPI库驱动显示屏 对于希望利用ESP32-S3控制电子墨水屏或其他类型的显示设备的应用开发者来说,可以采用专门为ESP8266和ESP32定制优化过的Waveshare PaperDisplay Arduino库——即`TFT_eSPI`库来实现这一目标。此库可通过Arduino IDE内置的库管理器轻松获取并安装至本地环境之中[^2]。 #### 配置LVGL图形界面支持 为了进一步增强基于ESP32-S3构建的人机交互系统的视觉体验,还可以集成轻量级且高效的GUI框架-LVGL (Light and Versatile Graphics Library) 。通过按照官方指南完成必要的软件包下载与设置工作之后,在Arduino环境中编写相应的UI逻辑变得异常简单快捷;同时需要注意的是,在实际操作过程中应当参照特定版本说明正确放置相关依赖项至指定路径之下以便顺利完成编译链接过程[^3]。 ```cpp // 示例:初始化LVGL void setup() { lv_init(); // 初始化显示器面板 extern disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.disp_flush = my_disp_flush; // 自定义刷新函数指针赋值给回调成员变量 lv_disp_drv_register(&disp_drv); // 注册显示驱动程序实例 // 创建简单的按钮控件作为演示用途 lv_obj_t *btn = lv_btn_create(lv_scr_act()); lv_obj_set_pos(btn, 10, 10); } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值