写在前面
前几天买了个tft屏幕,一路使用心路很曲折,故把踩坑过程写出来,方便日后查看
是一个st7789,240*240分辨率的屏幕
1 物理连接
网上全是各种各样不同的教程,给我整麻了,后面摸索出来了。
GPIO23—-SDA
GPIO18—-SCK
GPIO4—-RES
GPIO2—-DC
VCC—-5V(3V3都可以)
GND—-GND
似乎是线最好要等长,短一点更好,好像干扰还不小。
2 TFT_eSPI库的初始化
很像u8g2库的使用。
2.1 安装库,
如果你用的是arduino ide 可以直接在库管理里面搜这个库就有了,如果不是的话可以去这个链接下。
2.2 设置库
下一步就是找到项目文件夹下的libraries文件夹(也就是库文件存放的地方),打开TFT_eSPI文件夹,打开User_Setup_Select.h文件,然后注释掉user_setup,取消setup24的注释,大概就改成了这样子:
// This header file contains a list of user setup files and defines which one the
// compiler uses when the IDE performs a Verify/Compile or Upload.
//
// Users can create configurations for different boards and TFT displays.
// This makes selecting between hardware setups easy by "uncommenting" one line.
// The advantage of this hardware configuration method is that the examples provided
// with the library should work with immediately without any other changes being
// needed. It also improves the portability of users sketches to other hardware
// configurations and compatible libraries.
//
// Create a shortcut to this file on your desktop to permit quick access for editing.
// Re-compile and upload after making and saving any changes to this file.
// Customised User_Setup files are stored in the "User_Setups" folder.
// It is also possible for the user tft settings to be included with the sketch, see
// the "Sketch_with_tft_setup" generic example. This may be more convenient for
// multiple projects.
#ifndef USER_SETUP_LOADED // Lets PlatformIO users define settings in
// platformio.ini, see notes in "Tools" folder.
///////////////////////////////////////////////////////
// User configuration selection lines are below //
///////////////////////////////////////////////////////
// Only ONE line below should be uncommented to define your setup. Add extra lines and files as needed.
//#include <User_Setup.h> // Default setup is root library folder
//#include <User_Setups/Setup1_ILI9341.h> // Setup file for ESP8266 configured for my ILI9341
//#include <User_Setups/Setup2_ST7735.h> // Setup file for ESP8266 configured for my ST7735
//#include <User_Setups/Setup3_ILI9163.h> // Setup file for ESP8266 configured for my ILI9163
//#include <User_Setups/Setup4_S6D02A1.h> // Setup file for ESP8266 configured for my S6D02A1
//#include <User_Setups/Setup5_RPi_ILI9486.h> // Setup file for ESP8266 configured for my stock RPi TFT
//#include <User_Setups/Setup6_RPi_Wr_ILI9486.h> // Setup file for ESP8266 configured for my modified RPi TFT
//#include <User_Setups/Setup7_ST7735_128x128.h> // Setup file for ESP8266 configured for my ST7735 128x128 display
//#include <User_Setups/Setup8_ILI9163_128x128.h> // Setup file for ESP8266 configured for my ILI9163 128x128 display
//#include <User_Setups/Setup9_ST7735_Overlap.h> // Setup file for ESP8266 configured for my ST7735
//#include <User_Setups/Setup10_RPi_touch_ILI9486.h> // Setup file for ESP8266 configured for ESP8266 and RPi TFT with touch
//#include <User_Setups/Setup11_RPi_touch_ILI9486.h> // Setup file configured for ESP32 and RPi TFT with touch
//#include <User_Setups/Setup12_M5Stack_Basic_Core.h>// Setup file for the ESP32 based M5Stack (Basic Core only)
//#include <User_Setups/Setup13_ILI9481_Parallel.h> // Setup file for the ESP32 with parallel bus TFT
//#include <User_Setups/Setup14_ILI9341_Parallel.h> // Setup file for the ESP32 with parallel bus TFT
//#include <User_Setups/Setup15_HX8357D.h> // Setup file for ESP8266 configured for HX8357D
//#include <User_Setups/Setup16_ILI9488_Parallel.h> // Setup file for the ESP32 with parallel bus TFT
//#include <User_Setups/Setup17_ePaper.h> // Setup file for ESP8266 and any Waveshare ePaper display
//#include <User_Setups/Setup18_ST7789.h> // Setup file for ESP8266 configured for ST7789
//#include <User_Setups/Setup19_RM68140_Parallel.h> // Setup file configured for RM68140 with parallel bus
//#include <User_Setups/Setup20_ILI9488.h> // Setup file for ESP8266 and ILI9488 SPI bus TFT
//#include <User_Setups/Setup21_ILI9488.h> // Setup file for ESP32 and ILI9488 SPI bus TFT
//#include <User_Setups/Setup22_TTGO_T4.h> // Setup file for ESP32 and TTGO T4 version 1.2
//#include <User_Setups/Setup22_TTGO_T4_v1.3.h> // Setup file for ESP32 and TTGO T4 version 1.3
//#include <User_Setups/Setup23_TTGO_TM.h> // Setup file for ESP32 and TTGO TM ST7789 SPI bus TFT
#include <User_Setups/Setup24_ST7789.h> // Setup file for DSTIKE/ESP32/ESP8266 configured for ST7789 240 x 240
下一步就是去user_setup文件夹下面找到setup24那个库,改成这个样子:
// ST7789 240 x 240 display with no chip select line
#define USER_SETUP_ID 24
#define ST7789_DRIVER // Configure all registers
#define TFT_WIDTH 240
#define TFT_HEIGHT 240
//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
//#define TFT_INVERSION_ON
//#define TFT_INVERSION_OFF
// DSTIKE stepup
//#define TFT_DC 23
//#define TFT_RST 32
//#define TFT_MOSI 26
//#define TFT_SCLK 27
// Generic ESP32 setup
#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS -1 // Not connected
#define TFT_DC 2
#define TFT_RST 4 // Connect reset to ensure display initialises
// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation
//#define TFT_CS -1 // Define as not used
//#define TFT_DC PIN_D1 // Data Command control pin
//#define TFT_RST PIN_D4 // TFT reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST -1 // TFT reset pin connect to NodeMCU RST, must also then add 10K pull down to TFT SCK
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
#define SMOOTH_FONT
// #define SPI_FREQUENCY 27000000
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 20000000
#define SPI_TOUCH_FREQUENCY 2500000
// #define SUPPORT_TRANSACTIONS
这样基本的前置任务就做完了。
3 tft函数的使用
3.1 基本操作
首先要导入相关的库文件
#include <SPI.h>
#include <TFT_eSPI.h>
然后定义tft对象(参数是你的分辨率)
TFT_eSPI tft = TFT_eSPI(240, 240);
然后初始化tft对象
tft.init();
这样tft的那一堆方法就可以用啦,坐标系和opencv一样,左上角为原点(高中物理实验题:小球平抛你懂吧)
// 设置文本显示坐标,默认以文本左上角为参考点,可以改变参考点
tft.setCursor(10, 10);
// 设置文本颜色
tft.setTextColor(TFT_GREEN);
// 设置文本大小,文本大小范围为 1~7 的整数
tft.setTextSize(4);
// 设置字体编号 font,编号范围是 1、2、4、6、7、8,不同的编号代表不同的字体
tft.setTextFont(1);
下一步是定义颜色,这个屏幕采用了R5G6B5的色彩空间,所以我们可以用一些它定义好的颜色
#define TFT_BLACK 0x0000 /* 0, 0, 0 */
#define TFT_NAVY 0x000F /* 0, 0, 128 */
#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */
#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */
#define TFT_MAROON 0x7800 /* 128, 0, 0 */
#define TFT_PURPLE 0x780F /* 128, 0, 128 */
#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */
#define TFT_LIGHTGREY 0xD69A /* 211, 211, 211 */
#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */
#define TFT_BLUE 0x001F /* 0, 0, 255 */
#define TFT_GREEN 0x07E0 /* 0, 255, 0 */
#define TFT_CYAN 0x07FF /* 0, 255, 255 */
#define TFT_RED 0xF800 /* 255, 0, 0 */
#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */
#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */
#define TFT_WHITE 0xFFFF /* 255, 255, 255 */
#define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */
#define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */
#define TFT_PINK 0xFE19 /* 255, 192, 203 */ //Lighter pink, was 0xFC9F
#define TFT_BROWN 0x9A60 /* 150, 75, 0 */
#define TFT_GOLD 0xFEA0 /* 255, 215, 0 */
#define TFT_SILVER 0xC618 /* 192, 192, 192 */
#define TFT_SKYBLUE 0x867D /* 135, 206, 235 */
#define TFT_VIOLET 0x915C /* 180, 46, 226 */
全部的api在这里:
Sprite类是个啥一会说
//以下大多API对Sprite类也通用
//初始化
tft.init();
//填充全屏幕
tft.fillScreen(uint32_t color);
//屏幕旋转,参数为:0, 1, 2, 3,分别代表 0°、90°、180°、270°
tft.setRotation(uint8_t r);
//设置光标位置,font是可选参数
tft.setCursor(int16_t x, int16_t y, uint8_t font);
//设置字体颜色
tft.setTextColor(uint16_t color);
//设置文本颜色和背景色
tft.setTextColor(uint16_t fgcolor, uint16_t bgcolor);
//设置字体大小,文本大小范围为 1~7 的整数,特别注意: 字库7是仿7段数码屏的样式
tft.setTextSize(uint8_t size);
//加载字体
display.loadFont(Final_Frontier_28);
//括号中为示例,大小为28像素的平滑字体。
//使用平滑字体时最好用setTextColor同时设置好字体和背景颜色,否则可能会不平滑。
//卸载当前字体
display.unloadFont();
//打印
tft.print("Hello World!");
tft.println("Hello World!");
//绘制字符串
//居左
tft.drawString(String, int32_t x, int32_t y, uint8_t font);//font是可选参数
//居中
tft.drawCentreString(String, int32_t x, int32_t y, uint8_t font);//font是可选参数
//居右
tft.drawRightString(String, int32_t x, int32_t y, uint8_t font);//font是可选参数
//画点
tft.drawPixel(int32_t x, int32_t y, uint32_t color);
//画线
tft.drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint32_t color);
//画横线
tft.drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color);
//画竖线
tft.drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color);
//画圆
//空心圆
tft.drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color);
//实心圆
tft.fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color);
//空心椭圆
tft.drawEllipse(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
//实心椭圆
tft.fillEllipse(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
//画矩形
//空心矩形
tft.drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
//实心矩形
tft.fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
//空心圆角矩形
tft.drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color);
//实心圆角矩形
tft.drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color);
//画三角形
//空心三角形
tft.drawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, uint32_t color);
//实心三角形
tft.drawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, uint32_t color);
//显示图片
tft.pushImage(int32_t x, int32_t y, int32_t w, int32_t h, data);
3.2 刷新,局部刷新,刷不了新
假设我们有一个需要动态显示的变量,比如时间,那么最常想到的刷新就是给屏幕使用tft.fillScreen(uint32_t color);方法再显示刷新后的内容就可以了,这样在需要刷新频率很低的时候(比如每分钟一次)不会有什么很大的问题,但是如果是一个需要实时刷新的数据,这样就会让屏幕一直爆闪,很恼火,所以就会有局部刷新的需求
首先要了解tft库采用了一个覆盖显示的方法,也就是说过去的图像只能被覆盖,而不是擦除,基于这一点,我们给需要刷新的地方用背景的颜色覆盖上就好啦。
tft.fillRect(0, 108, 140, 28, TFT_BLACK);
tft.setCursor(0,108);
tft.print("hell world");
当然有别的方法也可以实现这个操作,就是用 sprite库
这个可以想象为一个显示屏上面的显示屏,你可以设置它的大小,位置,以及不和下面显示屏同步来进行刷新,这样闪屏就解决了。
我们来看一点点这个玩意自己的api
/*实例化*/
TFT_eSprite clk = TFT_eSprite(&tft);
//创建一个 宽x高像素 的sprite,返回一个指向RAM的指针
//如果需要,Sketch 可以将返回值转换为 (uint16_t*) 以获得 16 位深度
void* createSprite(int16_t width, int16_t height, uint8_t frames = 1);
void* getPointer(void);//如果未创建,则返回一个指向精灵或 nullptr 的指针,用户必须转换为指针类型
bool created(void); //如果精灵已经创建,则返回真
void deleteSprite(void);//删除精灵以释放 RAM
//设置或获取颜色深度为 4、8 或 16 位。可用于更改现有精灵的深度,但会将其清除为黑色,如果重新创建精灵,则返回一个新指针。
void* setColorDepth(int8_t b);
int8_t getColorDepth(void);
void drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t font);//在 Adafruit GLCD 或 freefont 中绘制单个字符
//在屏幕上绘制一个 unicode 字形。任何 UTF-8 解码都必须在调用 drawChar() 之前完成
int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font);
int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y);
//设置滚动区域,从左上角定义x,y,宽度和高度。颜色(可选,默认为黑色)用于填充滚动后的间隙
void setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color = TFT_BLACK);
//滚动 定义区域 dx,dy 像素。负值向上、左滚动;正值向右、下滚动。向上、向下滚动是可选的(默认是没有向上/向下滚动)。
//Sprite 坐标系不移动,移动的是像素
void scroll(int16_t dx, int16_t dy = 0),
void setRotation(uint8_t rotation);//设置Sprite 的旋转坐标(仅适用于 1位色深的Sprite ) 显示器内部硬件中的 CGRAM 旋转
uint8_t getRotation(void);
//将 Sprite 的旋转副本推送到具有可选透明颜色的 TFT
bool pushRotated(int16_t angle, uint32_t transp = 0x00FFFFFF); // Using fixed point maths
//将 Sprite 的旋转副本推送到另一个具有可选透明颜色的不同 Sprite
bool pushRotated(TFT_eSprite *spr, int16_t angle, uint32_t transp = 0x00FFFFFF);
//获取此 Sprite 旋转副本的 TFT 边界框
bool getRotatedBounds(int16_t angle, int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y);
//获取此 Sprite 的旋转副本的目标 Sprite 边界框
bool getRotatedBounds(TFT_eSprite *spr, int16_t angle, int16_t *min_x, int16_t *min_y,
int16_t *max_x, int16_t *max_y);
//获取旋转的 Sprite wrt 枢轴的 TFT 边界框
void getRotatedBounds(int16_t angle, int16_t w, int16_t h, int16_t xp, int16_t yp,
int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y);
uint16_t readPixel(int32_t x0, int32_t y0);//读取 x,y 处像素的颜色并以 565 格式返回值
uint16_t readPixelValue(int32_t x, int32_t y);//返回 x,y 处像素的数值(滚动时使用)
其他的方法都和tft库一模一样(我还是觉得直接覆盖比较好用)
3.3 俺的图图呢?
如果你想要在显示一张精妙的图片,需要对一张图片进行取模的操作
首先准备一张图片:
这里我的屏幕是正方形的,为了适配就用画图工具给裁剪了
然后打开image2lcd这个软件(有破解版,请自便)
这样搞完之后保存那个,把类型换成short(之后你就知道为啥了
打开程序存在的目录,把这个玩意丢进去
导入这个图片:
#include "tutu.c"
因为这个格式不是屏幕想要的,所以要重新写格式转换的函数
#define PI_BUF_SIZE 128
void showImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data){
int32_t dx = 0;
int32_t dy = 0;
int32_t dw = w;
int32_t dh = h*2;
if (x < 0) { dw += x; dx = -x; x = 0; }
if (y < 0) { dh += y; dy = -y; y = 0; }
if (dw < 1 || dh < 1) return;
CS_L;
data += dx + dy * w;
uint16_t buffer[PI_BUF_SIZE];
uint16_t* pix_buffer = buffer;
uint16_t high,low;
tft.setWindow(x, y, x + dw - 1, y + dh - 1);
// Work out the number whole buffers to send
uint16_t nb = (dw * dh) / (2 * PI_BUF_SIZE);
// Fill and send "nb" buffers to TFT
for (int32_t i = 0; i < nb; i++) {
for (int32_t j = 0; j < PI_BUF_SIZE; j++) {
high = pgm_read_word(&data[(i * 2 * PI_BUF_SIZE) + 2 * j + 1]);
low = pgm_read_word(&data[(i * 2 * PI_BUF_SIZE) + 2 * j ]);
pix_buffer[j] = (high<<8)+low;
}
tft.pushPixels(pix_buffer, PI_BUF_SIZE);
}
// Work out number of pixels not yet sent
uint16_t np = (dw * dh) % (2 * PI_BUF_SIZE);
// Send any partial buffer left over
if (np) {
for (int32_t i = 0; i < np; i++)
{
high = pgm_read_word(&data[(nb * 2 * PI_BUF_SIZE) + 2 * i + 1]);
low = pgm_read_word(&data[(nb * 2 * PI_BUF_SIZE) + 2 * i ]);
pix_buffer[i] = (high<<8)+low;
}
tft.pushPixels(pix_buffer, np);
}
CS_H;
}
showImage(0, 0, 240, 240,gImage_tutu);
参数分别是:图片左上角坐标,图片大小,库里面图片的名字
然后编译上传图片:
完美!
汉字的取模和使用和图片差不多(
这里就不说了(太懒了想去打派派
浏览量+1