TFT_eSPI — это одна из самых проработанных и эффективных библиотек драйверов для работы с дисплеями в среде Arduino IDE. Библиотека поддерживает множество контроллеров дисплеев и разные микроконтроллеры с которыми они могут взаимодействовать, включая: ESP32, RP2040, STM32.
В TFT_eSPI реализованы все основные функции для работы с компьютерной графикой:
- вывод геометрии: точки, линии, прямоугольники, окружности, эллипсы, включая сглаженную геометрию — antialiasing;
- вывод текста, включая сглаженные шрифты True Type;
- вывод файлов изображений.
Кроме того, TFT_eSPI умеет работать с сенсором дисплея.
Для демонстрации возможностей библиотеки используем дисплейный модуль с TFT матрицей и контроллером ILI9341.
Список необходимых компонентов
Для выполнения всех экспериментов в данном уроке, кроме самого модуля TFT дисплея, потребуется отладочная плата на основе ESP32. Подойдет плата из семейства графитов: Графит-32S, Графит-S2, Графит-S3. Также пригодится беспаечная макетная плата и немного проводов. Необходимые компоненты можно добавить в корзину прямо здесь, и затем оформить заказ в нашем интернет-магазине.
Подключение
Дисплей подключается по интерфейсу SPI, а значит для минимальной функциональности следует соединить питание и 4 линии интерфейса SPI (SCK, MISO, MOSI, CS):
- BL — контакт для контроля подсветки;
- SCK — синхроимпульс SPI;
- MISO — данные от дисплея (Master In) к устройству (Slave Out);
- MOSI — данные от контроллера (Master Out) к дисплею (Slave In);
- D_CS — выбор дисплея SPI (Chip Select);
- D_DC — линия для передачи команд устройству;
- D_RST — сброс памяти дисплея,
- SD_CS — выбор SD-карты SPI (Chip Select);
- T_CS — выбор сенсора SPI (Chip Select);
- T_IRQ — прерывание сенсора;
- GND — земля;
- VCC — питание.
Подключаем дисплей к отладочной плате Графит-S3. У данной платы SPI интерфейс, по умолчанию, привязан к контактам: MOSI-9, MISO-2, SCK-10. В этой инструкции мы не будем работать с microSD картой и сенсором, так что контакты SD_CS и T_CS пока можно не подключать.
| Графит-S3 | 3.3 | Gnd | 10 | 2 | 9 | 11 | 12 | 13 | 14 | 35 |
| Дисплей TFT 3.2 RobotClass | VCC | GND | SCK | MISO | MOSI | D_DC | D_RST | D_CS | SD_CS | T_CS |
Программа
Библиотеку TFT_eSPI можно установить через менеджер библиотек или напрямую из репозитория github.
Настройка TFT_eSPI
Для правильной работы библиотеки TFT_eSPI сначала следует настроить файл конфигурации User_Setup.h. Это необходимо сделать вручную, открыв в текстовом редакторе файл:
путь_к_библиотекам\Arduino\libraries\TFT_eSPI-master\User_Setup.h
Можно удалить всё содержимое этого файла и оставить только следующие строки:
#define USER_SETUP_INFO "User_Setup"
#define ILI9341_DRIVER
#define TFT_RGB_ORDER TFT_BGR
#define TFT_WIDTH 240
#define TFT_HEIGHT 320
#define TFT_INVERSION_OFF
#define TFT_MOSI 9
#define TFT_MISO 2
#define TFT_SCLK 10
#define TFT_CS 13
#define TFT_DC 11
#define TFT_RST 12
#define TOUCH_CS 35
#define LOAD_GLCD
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 20000000
#define SPI_TOUCH_FREQUENCY 2500000
Параметры TOUCH_CS и SPI_TOUCH_FREQUENCY нужны исключительно для работы с сенсором, если его нет — их можно пропустить.
Работа с геометрией
Первая программа будет просто закрашивать весь экран разными цветами. Начнём с подключения библиотеки TFT_eSPI.
#include "TFT_eSPI.h"
Далее создаём программный объект класса TFT_eSPI с именем tft.
TFT_eSPI tft = TFT_eSPI();
Внутри стартовой функции setup инициализируем драйвер дисплея методом init.
void setup() {
tft.init();
}
Вот и всё что нужно сделать для того чтобы дисплей заработал.
Экран будем закрашивать с помощью метода fillScreen, единственным аргументом которого является цвет заливки.
В файле TFT_eSPI.h есть список кодов для стандартных цветов. Также можно использовать конвертер цвета из 24-разрядов в 16-разрядов: https://tools.robotclass.ru/color_converter
#include "TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init(); // инициализация драйвера
}
void loop() {
// закрашивание экрана разными цветами
tft.fillScreen(TFT_RED);
delay(1000);
tft.fillScreen(TFT_GREEN);
delay(1000);
tft.fillScreen(TFT_BLUE);
delay(1000);
tft.fillScreen(TFT_BLACK);
delay(1000);
}
В следующем примере нарисуем несколько разных примитивов: прямоугольники, окружности, линии и точки.
По-умолчанию, экран у дисплея ориентирован вертикально: 240 — ширина, 320 — высота. Чтобы повернуть экран на 90 градусов используем метод setRotation с аргументом — 1 (сколько раз на 90 градусов надо повернуть, всего можно от 0 до 3).
#include "TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init(); // инициализация драйвера
tft.setRotation(1);
// заполнение экрана черным цветом
tft.fillScreen(TFT_BLACK);
// красный сплошной прямоугольник, координаты угла, размер, цвет
tft.fillRect(110, 70, 100, 100, TFT_RED);
// белый прямоугольник, координаты угла, размер, цвет
tft.drawRect(110, 70, 100, 100, TFT_WHITE);
// белый прямоугольник, координаты центра, радиус, цвет
tft.drawCircle(160, 120, 40, TFT_WHITE);
// белый сплошной прямоугольник, координаты центра, радиус, цвет
tft.fillCircle(160, 120, 35, TFT_CYAN);
// белая линия, координаты начала и конца, цвет
tft.drawLine(120, 80, 200, 160, TFT_WHITE);
// красный пиксель, координаты и цвет
tft.drawPixel(160, 120, TFT_RED);
}
void loop() {
}
Загружаем программу на отладочную плату.

Вывод текста
Теперь попробуем вывести текст. Начнём с обычного несглаженного шрифта.
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init(); // инициализация дисплея
tft.setRotation(1); // поворот на 90 градусов
tft.fillScreen(TFT_BLACK); // заливка фона чёрным цветом
tft.setCursor(70, 110); // x,y координаты текста
tft.setTextColor(TFT_WHITE); // цвет текста - белый
tft.setTextSize(3); // размер текста - 3 (7*3 = 21 точка)
tft.print("RobotClass"); // вывод текста
}
void loop() {
}
Результат — текст на середине экрана пиксельным шрифтом.

По-умолчанию библиотека не поддерживает русский язык. Однако, с помощью небольших манипуляция этого можно добиться. Подробности в нашем уроке на эту тему.
Сглаженный текст True Type
В отличие от обычного пиксельного шрифта, который можно масштабировать как угодно, шрифты TrueType хранят изображения каждого символа в заданном размере в памяти микроконтроллера. Чем больше размер шрифта, там больше памяти он занимает. Этот факт следует учитывать при разработке графических интерфейсов с разными шрифтами.
Для работы шрифтов в файле настроек User_Setup.h нужно добавить строки:
#define LOAD_GFXFF
#define SMOOTH_FONT
Эти настройки подключают заголовки TrueType шрифтов, которые лежат в папке /Fonts/… Но этого мало, каждый шрифт которым планируется воспользоваться, необходимо загрузить в память при помощи метода setFreeFont.
Возьмём, например, шрифт Orbitron. Откроем файл /Fonts/Orbitron_Light_24.h и найдём в нём определение шрифта вида:
const GFXfont Orbitron_Light_24 PROGMEM = {
(uint8_t *)Orbitron_Light_24Bitmaps,(GFXglyph *)Orbitron_Light_24Glyphs,0x20, 0x7D, 24};
Запоминаем имя переменной, в которой хранится шрифт: Orbitron_Light_24.
Теперь, в нашей программе загружаем шрифт, указываем &Orbitron_Light_24 в качестве аргумента метода setFreeFont.
При установке цвета обязательно указываем второй аргумент — цвет фона на котором планируем отрисовывать текст.
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
tft.setFreeFont(&Orbitron_Light_24); // загрузка в память шрифта
tft.setCursor(70, 120);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.println("RobotClass");
}
void loop() {
}
Результат — текст RobotClass красивым TrueType шрифтом на середине экрана.

Вся прелесть в том, что можно использовать какие-угодно ttf и woff шрифты. Включая кириллические. Подробности в нашем уроке на эту тему.
Вывод графических файлов
Теперь выведем на экран PNG файл. Сам файл можно хранить либо во внутренней флеш-памяти микроконтроллера: в основном разделе или в дополнительном — LittleFS, либо на внешнем накопителе, например, на той же microSD карте.
Здесь разберем способ, который потребляет много оперативной памяти, но позволяет быстро вывести изображение на экран. Этот способ подойдет для создания анимации.
Для начала поместим PNG файл с нужным разрешением в раздел LittleFS памяти микроконтроллера. Для примера, запишем в Графит-S3 картинку туманности с разрешением 320×240.
Для работы программы нам понадобятся две дополнительные библиотеки: LittleFS и PNGdec. Их можно установить через менеджер библиотек в Arduino IDE.
На первом этапе программы мы считываем файл из LittleFS и сохраняем его в оперативной памяти. Далее, извлекаем его из ОЗУ и выводим на дисплей.
#include <LittleFS.h>
#include <PNGdec.h>
#include <TFT_eSPI.h>
#define FileSys LittleFS
#define MAX_IMAGE_WIDTH 320
PNG png;
TFT_eSPI tft = TFT_eSPI();
int16_t xpos = 0;
int16_t ypos = 0;
void setup() {
FileSys.begin();
tft.init();
tft.setRotation(1);
// чтение файла из LittleFS в ОЗУ
fs::File file = LittleFS.open("/nebulae.png", "r");
uint32_t im_size = file.size();
uint8_t *image = (uint8_t*)malloc(im_size);
file.read(image, im_size);
file.close();
// чтение файла из ОЗУ и вывод на дисплей
int16_t rc = png.openRAM(image, im_size, pngDraw);
if( rc == PNG_SUCCESS ){
tft.startWrite();
rc = png.decode(NULL, 0);
png.close();
tft.endWrite();
}
}
void loop() {
}
void pngDraw(PNGDRAW *pDraw) {
uint16_t lineBuffer[MAX_IMAGE_WIDTH];
png.getLineAsRGB565(pDraw, lineBuffer, PNG_RGB565_BIG_ENDIAN, 0xffffffff);
tft.pushImage(xpos, ypos + pDraw->y, pDraw->iWidth, 1, lineBuffer);
}
Результат — изображение туманности во весь экран.

Полезные ссылки
Репозиторий GitHub библиотеки TFT_eSPI: