ESP32-C3 VScode + PIO Arduino环境下使用TFT_eSPI库 驱动两块0.96‘ ST7735S拼接后运行LVGL

LVGL部分的配置找其它人的嗷,至于为什么我之前已经写过一个Adafruit_GFX库(点此跳转)驱动,现在还要写一个TFT_eSPI库驱动的文章,是因为我后来发现Adafruit_GFX库的时钟速率就400多KHz。。实在是太太太慢了,然后不管我怎么改,发现速率就是不变的(即使代码里读出来的SPI速率已经改变了,但是实际示波器量出来依旧没变),所以没办法只能用TFT_eSPI库

使用TFT_eSPI库写双屏是一件很麻烦的事情,更何况ESP32-C3只有一个硬件SPI可以被我们使用。

接线

这里直接简单讲一下步骤哈,有空再完善:

  1. 使TFT_eSPI能够支持单片屏幕的显示(参考其它博主的博客即可)

例程:


#include <Arduino.h>
#include <TFT_eSPI.h>

TFT_eSPI tft =TFT_eSPI();

void setup(void) {
  tft.init();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLUE);
  tft.setCursor(20, 10);
  tft.setTextColor(TFT_WHITE);
  tft.setTextSize(2);
  tft.print("Hello ST7735!");
}

void loop() {
}
  1. 在TFT_eSPI/User_Setup.h文件里增加:


#define TFT_CS_Define 9
#define TFT_RST_Define 18

#define TFT_MOSI1 0
#define TFT_SCLK1 1
#define TFT_DC1 19
#define TFT_CS1 9
#define TFT_RST1 18


#define TFT_MOSI2 0
#define TFT_SCLK2 1
#define TFT_DC2 19
#define TFT_CS2 5
#define TFT_RST2 7

//随你加在文件的哪里,这仅仅只是把管脚定义加进去

  1. 因为只有CS和RST管脚是不一样的,所以可以从文件里原有的TFT_CS和TFT_RST两个定义右键转到引用,会发现只有TFT_eSPI.h里调用了他们,因此:

接下来把TFT_eSPI.h中所有与TFT_CS和TFT_RST相关的定义改成TFT_CS1、TFT_CS2、TFTRST1、TFT_RST2相关的定义,如图所示:

  1. 改完这里在TFT_eSPI.h的#include "TFT_eSPI.h"后面加上uint8_t TFT_choice;让这个变量来选择我们要控制哪块屏幕,对应地,为了让main.cpp里能调用TFT_choice这个变量,需要在TFT_eSPI.h里加上extern uint8_t TFT_choice;

然后编译下载一下例程看看是不是正常。

  1. 之后可以从例程的函数跳进来,会看到对RST管脚的调用(如果从init()函数跳进来)和对CS管脚的调用(如果从其它函数跳进来),同样地需要把他们改成类似于如下的代码:

是的,你的任务是把所有原本与RST、CS相关的代码全部修改一遍

  1. 改完之后调用这个程序:


#include <Arduino.h>
#include <TFT_eSPI.h>

TFT_eSPI tft =TFT_eSPI();

void setup(void) {    //注意如果你有背光引脚记得开启
    TFT_choice = 1;
    tft.init();
    tft.invertDisplay(true);
    tft.setRotation(1);
    tft.fillScreen(TFT_BLACK);
    tft.setTextSize(1);
    tft.setTextColor(TFT_WHITE);
    tft.setCursor(0, 0);
    tft.print("Hello ST7735!");
    TFT_choice = 2;
    tft.init();
    tft.invertDisplay(true);
    tft.setRotation(3);
    tft.fillScreen(TFT_BLACK);
    tft.setTextSize(1);
    tft.setTextColor(TFT_WHITE);
    tft.setCursor(0, 0);
    tft.print("Hello ST7735!");
}

void loop() {
}

只要两个屏幕都能正常显示,那TFT_eSPI库本身对双屏的底层支持就已经做好了(现在是双屏复制)

  1. 使其支持LVGL,做双屏连接

我这用的是两个160*80的屏幕,然后我做横向的屏幕拼接。

LVGL设置宽度320,高度80,

代码如下:


#include <Arduino.h>
#include <lvgl.h>

#include <TFT_eSPI.h>
#include <SPI.h>

#define TFT_WIDTH 320
#define TFT_HEIGHT 80

static lv_disp_draw_buf_t draw_buf;    //定义显示器变量
static lv_color_t buf[TFT_WIDTH * 10]; //定义刷新缓存

#define TFT_LEFT 2
#define TFT_RIGHT 1

TFT_eSPI tft = TFT_eSPI();

//写双屏函数
void Write_two_screens(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t *data_in)
{
    uint16_t *data = data_in;
    if(x1 < 160 && x2 < 160)        //只写左边屏
    {
        uint32_t w = (x2 - x1 + 1);
        uint32_t h = (y2 - y1 + 1);
        TFT_choice = TFT_LEFT;
        tft.startWrite();
        tft.setAddrWindow(x1,y1,w,h);
        tft.pushColors(data_in, w * h, true);
        tft.endWrite();
    }
    else if(x1 >= 160 && x2 >= 160)       //只写右边屏
    {
        uint32_t w = (x2 - x1 + 1);
        uint32_t h = (y2 - y1 + 1);
        TFT_choice = TFT_RIGHT;
        tft.startWrite();
        tft.setAddrWindow(x1 - 160,y1,w,h);
        tft.pushColors(data_in,w * h, true);
        tft.endWrite();
    }
    else                                  //写双屏
    {
        uint32_t w = (x2 - x1 + 1);
        uint32_t h = (y2 - y1 + 1);

        uint32_t i,j;
        uint32_t num_left = 0,num_right = 0;
        uint16_t data[320*10];
        for(j = 0;j < h;j ++)
        {
            for(i = 0;i < w;i ++)
            {
                if(x1 + i < 160) data[num_left ++] = data_in[j * w + i];
            }
        }

        TFT_choice = TFT_LEFT;
        tft.startWrite();
        tft.setAddrWindow(x1,y1,160 - x1,h);
        tft.pushColors(data,num_left, true);
        tft.endWrite();

        for(j = 0;j < h;j ++)
        {
            for(i = 0;i < w;i ++)
            {
                if(x1 + i >= 160) data[num_right ++] = data_in[j * w + i];
            }
        }

        TFT_choice = TFT_RIGHT;
        tft.startWrite();
        tft.setAddrWindow(0,y1,x2 - 159,h);     //单屏宽度-1
        tft.pushColors(data,num_right, true);
        tft.endWrite();
    }

    Serial.printf("x1 = %d,y1 = %d,x2 = %d,y2 = %d\r\n",x1,y1,x2,y2);
}

void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
    Write_two_screens(area->x1, area->y1,area->x2,area->y2,(uint16_t *)&(color_p->full));
    lv_disp_flush_ready(disp);
}
lv_obj_t *label_time;
lv_obj_t *label_time2;
void setup()   {
    Serial.begin(921600);
    while (!Serial);

    TFT_choice = TFT_LEFT;
    tft.init();
    tft.invertDisplay(true);
    tft.setRotation(1);
    tft.fillScreen(TFT_BLACK);
    tft.setTextSize(1);
    tft.setTextColor(TFT_WHITE);
    tft.setCursor(0, 0);
    TFT_choice = TFT_RIGHT;
    tft.init();
    tft.invertDisplay(true);
    tft.setRotation(3);
    tft.fillScreen(TFT_BLACK);
    tft.setTextSize(1);
    tft.setTextColor(TFT_WHITE);
    tft.setCursor(0, 0);

    lv_init();
    lv_disp_draw_buf_init(&draw_buf, buf, NULL, TFT_WIDTH * 10);

    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);

    disp_drv.hor_res = TFT_WIDTH;
    disp_drv.ver_res = TFT_HEIGHT;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    static lv_disp_t* disp1 = lv_disp_drv_register(&disp_drv);


    label_time = lv_label_create(lv_scr_act());
    lv_label_set_text_fmt(label_time, "%d",2);
    lv_obj_align(label_time, LV_ALIGN_BOTTOM_MID,0,0);
    lv_obj_set_style_text_font(label_time,&lv_font_montserrat_44,0);
    lv_obj_set_style_text_color(label_time,lv_color_hex(0x858585),0);

    label_time2 = lv_label_create(lv_scr_act());
    lv_label_set_text_fmt(label_time2, "%d:%d",11,20);
    lv_obj_align(label_time2, LV_ALIGN_TOP_RIGHT,0,0);
    lv_obj_set_style_text_font(label_time2,&lv_font_montserrat_20,0);
    lv_obj_set_style_text_color(label_time2,lv_color_hex(0x858585),0);
}

void loop() {
    delay(5);
    lv_timer_handler();
}


需要注意的是,如果你的代码烧录进去有关于Flash的报错,那就表示你用的buff太大了,给他分配小点的空间即可

另外,有人私信我说需要源码,我已经上传在附件里了,不出意外的话你可以在文章顶部看到它。

其它没啥了,有啥问题可以私信,只是我很有可能得过好几天才会看到

祝学习顺利,工作。。愉快吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值