SPI TFT 2.8寸液晶显示屏示例 ILI9341

硬件

1.模块

零知-标准板(其他型号也可以)- 零知标准板(点击购买)

SPI接口TFT屏-ili9341芯片-SPI接口TFT屏(点击购买)

2.连线

软件

(1)需要如下软件库


Adafruit-GFX-Library.7z(点击下载)
Adafruit_ILI9341.7z(点击下载)

(2)安装上面程序后,可以打开如下示例:

代码


												
	/**
	* 零知开源,让电子制作变得更简单。 - powered by 零知实验室
	* 2019年10月10日20:32:52
	*/
	#include "SPI.h"
	#include "Adafruit_GFX.h"
	#include "Adafruit_ILI9341.h"
	 
	// For the Adafruit shield, these are the default.
	#define TFT_DC 9
	#define TFT_CS 10
	 
	// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
	Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
	// If using the breakout, change pins as desired
	//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
	 
	void setup() {
	  Serial.begin(9600);
	  Serial.println("ILI9341 Test!"); 
	  
	  tft.begin();
	 
	  // read diagnostics (optional but can help debug problems)
	  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
	  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
	  x = tft.readcommand8(ILI9341_RDMADCTL);
	  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
	  x = tft.readcommand8(ILI9341_RDPIXFMT);
	  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
	  x = tft.readcommand8(ILI9341_RDIMGFMT);
	  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
	  x = tft.readcommand8(ILI9341_RDSELFDIAG);
	  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX); 
	   
	  Serial.println(F("Benchmark                Time (microseconds)"));
	  delay(10);
	  Serial.print(F("Screen fill              "));
	  Serial.println(testFillScreen());
	  delay(500);
	 
	  Serial.print(F("Text                     "));
	  Serial.println(testText());
	  delay(3000);
	 
	  Serial.print(F("Lines                    "));
	  Serial.println(testLines(ILI9341_CYAN));
	  delay(500);
	 
	  Serial.print(F("Horiz/Vert Lines         "));
	  Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE));
	  delay(500);
	 
	  Serial.print(F("Rectangles (outline)     "));
	  Serial.println(testRects(ILI9341_GREEN));
	  delay(500);
	 
	  Serial.print(F("Rectangles (filled)      "));
	  Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA));
	  delay(500);
	 
	  Serial.print(F("Circles (filled)         "));
	  Serial.println(testFilledCircles(10, ILI9341_MAGENTA));
	 
	  Serial.print(F("Circles (outline)        "));
	  Serial.println(testCircles(10, ILI9341_WHITE));
	  delay(500);
	 
	  Serial.print(F("Triangles (outline)      "));
	  Serial.println(testTriangles());
	  delay(500);
	 
	  Serial.print(F("Triangles (filled)       "));
	  Serial.println(testFilledTriangles());
	  delay(500);
	 
	  Serial.print(F("Rounded rects (outline)  "));
	  Serial.println(testRoundRects());
	  delay(500);
	 
	  Serial.print(F("Rounded rects (filled)   "));
	  Serial.println(testFilledRoundRects());
	  delay(500);
	 
	  Serial.println(F("Done!"));
	 
	}
	 
	 
	void loop(void) {
	  for(uint8_t rotation=0; rotation<4; rotation++) {
	    tft.setRotation(rotation);
	    testText();
	    delay(1000);
	  }
	}
	 
	unsigned long testFillScreen() {
	  unsigned long start = micros();
	  tft.fillScreen(ILI9341_BLACK);
	  yield();
	  tft.fillScreen(ILI9341_RED);
	  yield();
	  tft.fillScreen(ILI9341_GREEN);
	  yield();
	  tft.fillScreen(ILI9341_BLUE);
	  yield();
	  tft.fillScreen(ILI9341_BLACK);
	  yield();
	  return micros() - start;
	}
	 
	unsigned long testText() {
	  tft.fillScreen(ILI9341_BLACK);
	  unsigned long start = micros();
	  tft.setCursor(0, 0);
	  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
	  tft.println("Hello World!");
	  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
	  tft.println(1234.56);
	  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
	  tft.println(0xDEADBEEF, HEX);
	  tft.println();
	  tft.setTextColor(ILI9341_GREEN);
	  tft.setTextSize(5);
	  tft.println("Groop");
	  tft.setTextSize(2);
	  tft.println("I implore thee,");
	  tft.setTextSize(1);
	  tft.println("my foonting turlingdromes.");
	  tft.println("And hooptiously drangle me");
	  tft.println("with crinkly bindlewurdles,");
	  tft.println("Or I will rend thee");
	  tft.println("in the gobberwarts");
	  tft.println("with my blurglecruncheon,");
	  tft.println("see if I don't!");
	  return micros() - start;
	}
	 
	unsigned long testLines(uint16_t color) {
	  unsigned long start, t;
	  int           x1, y1, x2, y2,
	                w = tft.width(),
	                h = tft.height();
	 
	  tft.fillScreen(ILI9341_BLACK);
	  yield();
	   
	  x1 = y1 = 0;
	  y2    = h - 1;
	  start = micros();
	  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
	  x2    = w - 1;
	  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
	  t     = micros() - start; // fillScreen doesn't count against timing
	 
	  yield();
	  tft.fillScreen(ILI9341_BLACK);
	  yield();
	 
	  x1    = w - 1;
	  y1    = 0;
	  y2    = h - 1;
	  start = micros();
	  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
	  x2    = 0;
	  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
	  t    += micros() - start;
	 
	  yield();
	  tft.fillScreen(ILI9341_BLACK);
	  yield();
	 
	  x1    = 0;
	  y1    = h - 1;
	  y2    = 0;
	  start = micros();
	  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
	  x2    = w - 1;
	  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
	  t    += micros() - start;
	 
	  yield();
	  tft.fillScreen(ILI9341_BLACK);
	  yield();
	 
	  x1    = w - 1;
	  y1    = h - 1;
	  y2    = 0;
	  start = micros();
	  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
	  x2    = 0;
	  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
	 
	  yield();
	  return micros() - start;
	}
	 
	unsigned long testFastLines(uint16_t color1, uint16_t color2) {
	  unsigned long start;
	  int           x, y, w = tft.width(), h = tft.height();
	 
	  tft.fillScreen(ILI9341_BLACK);
	  start = micros();
	  for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
	  for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
	 
	  return micros() - start;
	}
	 
	unsigned long testRects(uint16_t color) {
	  unsigned long start;
	  int           n, i, i2,
	                cx = tft.width()  / 2,
	                cy = tft.height() / 2;
	 
	  tft.fillScreen(ILI9341_BLACK);
	  n     = min(tft.width(), tft.height());
	  start = micros();
	  for(i=2; i<n; i+=6) {
	    i2 = i / 2;
	    tft.drawRect(cx-i2, cy-i2, i, i, color);
	  }
	 
	  return micros() - start;
	}
	 
	unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
	  unsigned long start, t = 0;
	  int           n, i, i2,
	                cx = tft.width()  / 2 - 1,
	                cy = tft.height() / 2 - 1;
	 
	  tft.fillScreen(ILI9341_BLACK);
	  n = min(tft.width(), tft.height());
	  for(i=n; i>0; i-=6) {
	    i2    = i / 2;
	    start = micros();
	    tft.fillRect(cx-i2, cy-i2, i, i, color1);
	    t    += micros() - start;
	    // Outlines are not included in timing results
	    tft.drawRect(cx-i2, cy-i2, i, i, color2);
	    yield();
	  }
	 
	  return t;
	}
	 
	unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
	  unsigned long start;
	  int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
	 
	  tft.fillScreen(ILI9341_BLACK);
	  start = micros();
	  for(x=radius; x<w; x+=r2) {
	    for(y=radius; y<h; y+=r2) {
	      tft.fillCircle(x, y, radius, color);
	    }
	  }
	 
	  return micros() - start;
	}
	 
	unsigned long testCircles(uint8_t radius, uint16_t color) {
	  unsigned long start;
	  int           x, y, r2 = radius * 2,
	                w = tft.width()  + radius,
	                h = tft.height() + radius;
	 
	  // Screen is not cleared for this one -- this is
	  // intentional and does not affect the reported time.
	  start = micros();
	  for(x=0; x<w; x+=r2) {
	    for(y=0; y<h; y+=r2) {
	      tft.drawCircle(x, y, radius, color);
	    }
	  }
	 
	  return micros() - start;
	}
	 
	unsigned long testTriangles() {
	  unsigned long start;
	  int           n, i, cx = tft.width()  / 2 - 1,
	                      cy = tft.height() / 2 - 1;
	 
	  tft.fillScreen(ILI9341_BLACK);
	  n     = min(cx, cy);
	  start = micros();
	  for(i=0; i<n; i+=5) {
	    tft.drawTriangle(
	      cx    , cy - i, // peak
	      cx - i, cy + i, // bottom left
	      cx + i, cy + i, // bottom right
	      tft.color565(i, i, i));
	  }
	 
	  return micros() - start;
	}
	 
	unsigned long testFilledTriangles() {
	  unsigned long start, t = 0;
	  int           i, cx = tft.width()  / 2 - 1,
	                   cy = tft.height() / 2 - 1;
	 
	  tft.fillScreen(ILI9341_BLACK);
	  start = micros();
	  for(i=min(cx,cy); i>10; i-=5) {
	    start = micros();
	    tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
	      tft.color565(0, i*10, i*10));
	    t += micros() - start;
	    tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
	      tft.color565(i*10, i*10, 0));
	    yield();
	  }
	 
	  return t;
	}
	 
	unsigned long testRoundRects() {
	  unsigned long start;
	  int           w, i, i2,
	                cx = tft.width()  / 2 - 1,
	                cy = tft.height() / 2 - 1;
	 
	  tft.fillScreen(ILI9341_BLACK);
	  w     = min(tft.width(), tft.height());
	  start = micros();
	  for(i=0; i<w; i+=6) {
	    i2 = i / 2;
	    tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));
	  }
	 
	  return micros() - start;
	}
	 
	unsigned long testFilledRoundRects() {
	  unsigned long start;
	  int           i, i2,
	                cx = tft.width()  / 2 - 1,
	                cy = tft.height() / 2 - 1;
	 
	  tft.fillScreen(ILI9341_BLACK);
	  start = micros();
	  for(i=min(tft.width(), tft.height()); i>20; i-=6) {
	    i2 = i / 2;
	    tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
	    yield();
	  }
	 
	  return micros() - start;
	}				
						

以下为示例刷图效果图片:

以下为在零知ESP32上的演示示例:

1、硬件连接

然后如果有触摸的话,可以把IRQ连接到16脚,T_CS连接17脚,就可以进行触摸控制了。

2、软件程序

这里使用LVGL和tft_eSPI两个库进行GUI界面演示,程序如下:


												
	#include <lvgl.h>
	#include <Ticker.h>
	#include <TFT_eSPI.h>
	#include <XPT2046_Touchscreen.h>
	 
	#include "lv_test_theme.h"
	#include "lv_test_theme_1.h"
	 
	#define LVGL_TICK_PERIOD 20
	 
	#define CS_PIN  17 // Chip Select pin
	#define irq_pin 16 //IRQ pin
	 
	Ticker tick; /* timer for interrupt handler */
	TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
	XPT2046_Touchscreen ts(CS_PIN, irq_pin);
	 
	////////////////////////////////////////////////////////
	////////////////////////////////////////////////////////
	//// LVGL /////////////////////////////////////////////
	static lv_disp_buf_t disp_buf;
	static lv_color_t buf[LV_HOR_RES_MAX * 10];
	 
	/* 与LCD驱动关联 */
	void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
	{
	     
	    uint16_t c;
	     
	    tft.startWrite(); /* Start new TFT transaction */
	    tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */
	    for (int y = area->y1; y <= area->y2; y++) {
	        for (int x = area->x1; x <= area->x2; x++) {
	            c = color_p->full;
	            tft.writeColor(c, 1);
	            color_p++;
	        }
	    }
	    tft.endWrite(); /* terminate TFT transaction */
	    lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
	}
	 
	/* 中断 ms */
	static void lv_tick_handler(void)
	{
	     
	    lv_tick_inc(LVGL_TICK_PERIOD);
	}
	 
	/* 输入设备:touchpad */
	bool my_touchpad_read(lv_indev_drv_t * indev, lv_indev_data_t * data)
	{
	    static lv_coord_t last_x = 0;
	    static lv_coord_t last_y = 0;
	     
	    /*Save the state and save the pressed coordinate*/
	    data->state = ts.touched() ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
	    if(data->state == LV_INDEV_STATE_PR){
	        TS_Point p = ts.getPoint();
	         
	        //convert to lcd position
	        last_x = LV_HOR_RES-(p.x *LV_HOR_RES)/4095;       /*TODO save the current X coordinate*/
	        last_y = LV_VER_RES-(p.y *LV_VER_RES)/4095;       /*TODO save the current Y coordinate*/
	         
	        Serial.print("touched:");
	        Serial.print(last_x);Serial.print(",");Serial.println(last_y);
	    }
	     
	    /*Set the coordinates (if released use the last pressed coordinates)*/
	    data->point.x = last_x;
	    data->point.y = last_y;
	     
	    return false; /*Return `false` because we are not buffering and no more data to read*/
	}
	 
	void tft_touch_init()
	{
	    ts.begin(); //Begin TouchScreen.
	    tft.begin(); /* TFT init */
	    tft.setRotation(1); /* Landscape orientation */
	}
	 
	void lvgl_setup()
	{
	    lv_init();
	     
	    lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);
	     
	    /*Initialize the display*/
	    lv_disp_drv_t disp_drv;
	    lv_disp_drv_init(&disp_drv);
	    disp_drv.hor_res = LV_HOR_RES_MAX;
	    disp_drv.ver_res = LV_VER_RES_MAX;
	    disp_drv.flush_cb = my_disp_flush;
	    disp_drv.buffer = &disp_buf;
	    lv_disp_drv_register(&disp_drv);
	     
	     
	    /*Initialize the touch pad*/
	    lv_indev_drv_t indev_drv;
	    lv_indev_drv_init(&indev_drv);
	    indev_drv.type = LV_INDEV_TYPE_POINTER;
	    indev_drv.read_cb = my_touchpad_read;
	    lv_indev_drv_register(&indev_drv);
	     
	    /*Initialize the graphics library's tick*/
	    tick.attach_ms(LVGL_TICK_PERIOD, lv_tick_handler);
	}
	 
	void setup() {
	     
	    Serial.begin(9600); /* prepare for possible serial debug */
	     
	    //tft和touch 设置
	    tft_touch_init();
	     
	    //lvgl 相关设置和初始化
	    lvgl_setup();
	     
	    //lvgl demo
	    lv_test_theme();
	     
	    //    lv_test_theme_1(lv_theme_night_init(210, NULL));
	    //  lv_test_theme_1(lv_theme_night_init(100, NULL));
	    //  lv_test_theme_1(lv_theme_material_init(210, NULL));
	    //  lv_test_theme_1(lv_theme_alien_init(210, NULL));
	//  lv_test_theme_1(lv_theme_zen_init(210, NULL));
	    //  lv_test_theme_1(lv_theme_nemo_init(210, NULL));
	    //  lv_test_theme_1(lv_theme_mono_init(210, NULL));
	    //  lv_test_theme_1(lv_theme_default_init(210, NULL));
	     
	}
	 
	void loop() {
	    // put your main code here, to run repeatedly:
	     
	    lv_task_handler();
	    /*If 'lv_tick_inc(5)' is not called in a Timer then call it here*/
	    delay(5);             /*Wait a little*/
	}
						

完整工程代码:


lvgl_demo_esp32.rar(点击下载)

测试验证