ST7735: цветной TFT-дисплей для Arduino и ESP32 — подключение, код и настройка

ST7735: цветной TFT-дисплей для Arduino и ESP32 — подключение, код и настройка

Дисплеи ST7735: 128×160, 128×128 и 80×160, распиновка SPI, питание и подсветка, подключение к Arduino и ESP32, код, настройка цветов и устранение ошибок

За 20 секунд: ST7735 — популярный контроллер цветных TFT-дисплеев размером от 0,96 до 1,8 дюйма. Модуль общается по SPI, а не по I2C, даже если контакты подписаны SDA и SCL. Для запуска нужны пять сигналов: SCK, SDA/MOSI, CS, DC и RST, плюс питание и подсветка BL. Подключается к Arduino Uno/Nano и ESP32 через аппаратный SPI, работает с библиотеками Adafruit GFX и «Adafruit ST7735 and ST7789». Главные подводные камни: логика 3,3 В у дешёвых модулей, неправильная таблица инициализации (смещение картинки и обрезанные края) и белый экран при ошибке в подключении.

ST7735 — один из самых дешёвых способов добавить в проект цветной экран. На нём строят домашние метеостанции, мини-терминалы, индикаторы станций с ЧПУ, часы, плееры и портативные измерительные приборы. Модуль стоит дешевле стакана кофе, занимает мало места и рисует текст, графику и растровые картинки.

Но у новичков он регулярно вызывает вопросы. Экран остаётся белым. Картинка сдвинута, и по краям видны полосы. Красный и синий поменялись местами. Надписи SDA и SCL сбивают с толку — их хочется подключать к I2C. А на модуле 80×160 с таб-вариантом Mini вообще ничего не отображается, пока не выбран правильный вариант инициализации.

Разберём всё по порядку.

Что такое ST7735

ST7735 — контроллер ЖК-дисплеев от компании Sitronix. Он управляет матрицей, содержит память кадра (GRAM), встроенный контроллер питания и последовательный интерфейс. Сам по себе чип — не экран, а «мозг» модуля. Дисплейная панель с матрицей и breakout-плата с колодкой контактов образуют готовый модуль, который вы держите в руках.

Контроллер рассчитан на матрицы до 132×162 пикселя. Реальные модули используют распространённые панели:

МодульРазрешениеДиагональТипичный вариант инициализации
1,8"128×1601,8 дюймаINITR_BLACKTAB или INITR_GREENTAB/INITR_REDTAB
1,44"128×1281,44 дюймаINITR_144GREENTAB
0,96"–1,0"80×1600,96–1,0 дюймаINITR_MINI160x80

Разрешение 128×160 означает 128 пикселей по ширине и 160 по высоте в портретной ориентации. Экран показывает 18-битный цвет, который в коде передаётся как 16-битное значение RGB565. Цвета в библиотеках Adafruit задаются константами ST77XX_BLACK, ST77XX_RED, ST77XX_GREEN, ST77XX_BLUE, ST77XX_YELLOW, ST77XX_WHITE и так далее.

Почему SDA и SCL — это не I2C

На многих платах контакты подписаны SDA и SCL или даже SDA/MOSI и SCL/SCK. Это часто путает.

Внутри ST7735 используется только SPI. Исторические подписи взялись от модулей, где один и тот же контакт разводился под оба стандарта. На практике:

  • SDA на плате ST7735 — это линия данных SPI, то есть MOSI (Master Out, Slave In). Данные контроллер только принимает, отдельной линии чтения MISO у модуля нет.
  • SCL или SCK — это тактирующий сигнал SPI.

Пытаться подключать такой экран к I2C-шине I2C-сканером бесполезно: адреса у него нет, и в списке устройств он не появится.

Распиновка модуля

Типичная плата 1,8 дюйма имеет восемь контактов:

Контакт на платеАльтернативные подписиНазначение
VCCVDD, 3.3VПитание логики и матрицы
GNDVSSОбщий провод
CSTFT_CSВыбор чипа SPI (Chip Select), активный LOW
RESETRST, RESАппаратный сброс контроллера, активный LOW
A0DC, RS, D/CData/Command: выбор между командой и данными
SDAMOSI, DINДанные SPI от контроллера к экрану
SCKSCL, CLKТактовый сигнал SPI
LEDBL, BLC, BKПодсветка; чаще всего уже подключена к питанию через транзистор на плате

У модулей 0,96" и 1,44" подписи почти те же, но порядок контактов может отличаться. Перед подключением всегда сверяйтесь с маркировкой именно вашей платы.

Пин A0/DC — самый важный для понимания. По SPI в экран идут и команды («установить адрес окна», «начать запись в память»), и данные (значения пикселей). Логический уровень на DC говорит контроллеру, что именно сейчас передаётся: LOW — команда, HIGH — данные. Именно поэтому для дисплея нужны пять сигналов, а не три, как для простых SPI-датчиков.

Питание и логические уровни

Здесь кроется главный практический вопрос: можно ли питать модуль от 5 В?

  • Дешёвые «голые» модули без стабилизатора рассчитаны на питание 3,3 В. Их логические входы тоже ожидают уровни около 3,3 В.
  • Часть модулей (включая оригинальные breakout-платы Adafruit) имеет встроенный стабилизатор и согласование уровней, и производитель прямо заявляет совместимость и с 5 В, и с 3,3 В логикой.
  • Маркировка продавца «5V» на карточке товара не всегда отражает реальную схему платы.

Практические рекомендации:

  1. Для ESP32 и RP2040 всё просто: питайте модуль от 3,3 В и подключайте сигналы напрямую.
  2. Для Arduino Uno/Nano с 5-вольтовой логикой самый надёжный вариант — модуль с подтверждённой поддержкой 5 В. Если модуль без стабилизатора, используйте преобразователь уровней на линиях SCK, SDA, CS, DC, RST.
  3. Многие дешёвые модули 1,8" годами работают от 5 В без преобразователя, но это выходит за рамки спецификации чипа. Решение «подключил напрямую — работает» не гарантирует стабильность на другой партии плат.
  4. Подсветка LED/BL на большинстве модулей управляется транзистором и допускает прямое подключение к питанию. Если подсветку нужно включать и выключать программно, проверьте схему своей платы: на некоторых модулях BL уже подтянут к питанию, и разрывать её пином нельзя.

Подключение к Arduino Uno/Nano

Используем аппаратный SPI. На Uno и Nano он жёстко закреплён за выводами 11 (MOSI) и 13 (SCK). Остальные сигналы можно назначить на любые свободные цифровые пины.

ST7735 1.8"      Arduino Uno/Nano
─────────────    ────────────────
VCC      ───────  3.3V  (или 5V, если модуль поддерживает)
GND      ───────  GND
CS       ───────  D10
RESET    ───────  D8
A0/DC    ───────  D9
SDA      ───────  D11  (MOSI)
SCK      ───────  D13  (SCK)
LED      ───────  3.3V / 5V (или пин с PWM для регулировки)

Номера пинов CS = 10, DC = 9, RST = 8 выбраны не случайно — они совпадают с примерами библиотеки Adafruit, поэтому чужие скетчи из интернета заработают без правок.

Подключение к ESP32

На ESP32 удобнее всего использовать шину VSPI с выводами по умолчанию: SCK = GPIO18, MOSI = GPIO23. Сигналы CS, DC и RST можно повесить на любые свободные GPIO.

ST7735 1.8"      ESP32 DevKit
─────────────    ─────────────────
VCC      ───────  3V3
GND      ───────  GND
CS       ───────  GPIO5   (VSPI CS по умолчанию)
RESET    ───────  GPIO4
A0/DC    ───────  GPIO2
SDA      ───────  GPIO23  (VSPI MOSI)
SCK      ───────  GPIO18  (VSPI SCK)
LED      ───────  3V3

Ничего паять не нужно: все сигналы у ESP32 уже 3,3-вольтовые. Не забудьте только, что GPIO2 участвует в процедуре загрузки ESP32 — если экран мешает прошивке, перенесите DC на другой пин, например GPIO16. Подробнее о безопасных выводах — в статье про .

Установка библиотек

Нужны две библиотеки от Adafruit:

  1. Adafruit GFX Library — графический движок: линии, прямоугольники, круги, текст, шрифты.
  2. Adafruit ST7735 and ST7789 Library — драйвер конкретно этого контроллера. Раньше она называлась Adafruit-ST7735-Library, сейчас объединена с поддержкой ST7789.

Установка через Arduino IDE:

  1. Меню Скетч → Подключить библиотеку → Управлять библиотеками.
  2. В поиске введите ST7735.
  3. Установите «Adafruit ST7735 and ST7789 Library».
  4. Arduino IDE предложит установить зависимости — согласитесь, среди них будет Adafruit GFX.

Для PlatformIO добавьте в platformio.ini:

lib_deps =
  adafruit/Adafruit GFX Library
  adafruit/Adafruit ST7735 and ST7789 Library

Первый скетч: проверка экрана

Скетч заливает экран цветом, рисует рамку и выводит текст. Ничего лишнего, но по нему сразу видно, правильно ли выбрана таблица инициализации.

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>

// Пины для Arduino Uno/Nano
#define TFT_CS   10
#define TFT_DC    9
#define TFT_RST   8

// Для ESP32 закомментируйте строки выше и используйте:
// #define TFT_CS   5
// #define TFT_DC   2
// #define TFT_RST  4

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

void setup() {
  Serial.begin(9600);
  Serial.println("ST7735 test");

  // Для модуля 1.8" 128x160 начните с этого варианта:
  tft.initR(INITR_BLACKTAB);

  // Альтернативы для других модулей:
  // tft.initR(INITR_GREENTAB);    // 1.8", старые партии
  // tft.initR(INITR_REDTAB);      // 1.8", ещё один вариант
  // tft.initR(INITR_144GREENTAB); // 1.44" 128x128
  // tft.initR(INITR_MINI160x80);  // 0.96"/1.0" 80x160

  Serial.println("Initialized");

  uint16_t time = millis();
  tft.fillScreen(ST77XX_BLACK);
  time = millis() - time;
  Serial.print("fillScreen: "); Serial.print(time); Serial.println(" ms");

  // Крупный текст
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.setCursor(10, 20);
  tft.println("ARDULOVE");

  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(1);
  tft.setCursor(10, 50);
  tft.println("ST7735 128x160 TFT");

  // Рамка по краям — проверка, что ничего не обрезано
  tft.drawRect(0, 0, tft.width(), tft.height(), ST77XX_RED);
}

void loop() {
  // Мигание цветом, чтобы убедиться, что экран обновляется
  tft.invertDisplay(true);
  delay(500);
  tft.invertDisplay(false);
  delay(500);
}

Если на экране появился чёрный фон, жёлтая надпись, зелёная строка и красная рамка ровно по краям — модуль подключён правильно.

Функция tft.invertDisplay() меняет местами чёрный и белый и удобна для быстрой проверки, что картинка живая, а не зависла.

Таблицы инициализации: почему картинка сдвинута

ST7735 выпускается в разных версиях для разных панелей, и в памяти контроллера окно вывода может начинаться не с нуля. Библиека Adafruit учитывает это набором «табов» — вариантов инициализации. Если таб не совпал с реальной панелью, симптомы такие:

  • картинка сдвинута на несколько пикселей, у одного края цветная полоса;
  • углы рамки обрезаны, рамка «уехала» за край;
  • изображение есть, но по краям видны полосы мусора;
  • у Mini-модуля 80×160 при неправильном табе экран остаётся пустым или показывает мусор.

Решение — перебрать варианты initR():

МодульЧто пробовать
1,8" 128×160INITR_BLACKTAB, затем INITR_GREENTAB, затем INITR_REDTAB
1,44" 128×128INITR_144GREENTAB
0,96"/1,0" 80×160INITR_MINI160x80

Правильный таб — тот, при котором рамка из скетча выше видна целиком, без сдвигов и обрезания.

Цвета перепутаны: красный стал синим

Ещё одна особенность партий ST7735 — порядок цветовых каналов. У части панелей формат BGR вместо RGB. Внешне это выглядит так: вы рисуете красный, а на экране синий, и наоборот; жёлтый и голубой тоже меняются местами.

Часто правильный таб из предыдущего раздела заодно решает и проблему цвета. Если нет, в новых версиях библиотеки есть функция:

tft.setRGB(true);   // RGB-порядок
// или
tft.setRGB(false);  // BGR-порядок

Если ваша версия библиотеки эту функцию не знает, обновите библиотеку или используйте функцию invertDisplay() для инверсии — но учтите, что инверсия меняет все цвета, а не только порядок каналов.

Поворот экрана

Экран можно повернуть программно на 90° шагами:

tft.setRotation(0);  // портрет, 128x160
tft.setRotation(1);  // пейзаж, 160x128
tft.setRotation(2);  // портрет вверх ногами
tft.setRotation(3);  // пейзаж вверх ногами

После setRotation() функции tft.width() и tft.height() возвращают актуальные размеры, поэтому код отрисовки не нужно переписывать под каждую ориентацию.

Русский текст

Штатный шрифт Adafruit GFX содержит только ASCII, поэтому tft.print("Привет") выведет каракули или ничего. Варианты решения:

  1. Свой шрифт с кириллицей. Сгенерируйте GFX-шрифт из TTF/OTF-файла онлайн-конвертером (например, font converter от Adafruit или DIY-инструменты на Python/PIL), выбрав нужную кодировку Unicode, и подключите через tft.setFont(&my_cyrillic_font);. Это самый правильный путь: шрифт влезает во flash, а не в RAM.
  2. Библиотеки с готовыми кириллическими шрифтами. В экосистеме Arduino есть сборники GFX-шрифтов с русскими глифами — можно взять готовый вместо конвертации своего.
  3. Транслит или английский. Для приборных экранов иногда проще вывести TEMP 23.5C, чем возиться со шрифтами.

Для ESP32 есть и альтернативная библиотека TFT_eSPI — она быстрее за счёт DMA, поддерживает спрайты и загрузку шрифтов с кириллицей. Если проект перерастает Adafruit GFX, посмотрите в её сторону.

Обновление чисел без мерцания

Классическая задача: метеостанция раз в секунду выводит температуру. Если просто вызывать tft.print() поверх старого значения, цифры будут накладываться друг на друга.

Простейшее решение — стирать область перед выводом:

void printValue(int x, int y, float value) {
  tft.fillRect(x, y, 80, 16, ST77XX_BLACK);  // стираем зону числа
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(2);
  tft.setCursor(x, y);
  tft.print(value, 1);
}

Более продвинутый способ — двойная буферизация через спрайты (в TFT_eSPI) или частичная перерисовка только изменившихся символов. Для большинства любительских приборов достаточно fillRect().

Вывод картинок

Растровое изображение нужно перевести в массив RGB565 и хранить во flash. Стандартный инструмент — image2cpp (веб-конвертер) или LCD Assistant:

  1. Подготовьте картинку нужного размера, например 128×128.
  2. Конвертируйте в массив uint16_t в формате RGB565.
  3. Поместите массив в PROGMEM.
  4. Выведите через tft.drawRGBBitmap(x, y, bitmap, w, h);.

Учитывайте объём: картинка 128×128 занимает 32 КБ flash. Полноэкранная 128×160 — 40 КБ. Для Uno с её 32 КБ это уже не влезет, а для ESP32 — без проблем.

Совместное использование с microSD

Многие модули 1,8" выпускаются со слотом microSD на той же плате. Карта и дисплей сидят на одном SPI: общие SCK и MOSI, но отдельные CS. Пока вы обращаетесь к дисплею, его CS низкий, а CS карты высокий, и наоборот. Дисплей не использует MISO — чтение идёт только с карты.

Типичная схема для Uno:

Дисплей: CS=D10, DC=D9, RST=D8, SDA=D11, SCK=D13
Карта:   CS=D4,          MOSI=D11, MISO=D12, SCK=D13

В коде перед работой с картой не забывайте завершать транзакции с дисплеем — при использовании стандартных библиотек SPI.beginTransaction()/endTransaction() это происходит автоматически.

Диагностика проблем

Экран белый и ничего не показывает

Белый экран с работающей подсветкой означает, что матрица жива, но контроллер не получает команды. Проверьте:

  • питание VCC и GND — частая ошибка при подключении к макетке;
  • все пять сигналов: SCK, SDA, CS, DC, RST;
  • не перепутаны ли местами DC и RST — это самая частая ошибка;
  • правильность пинов в #define — особенно если скетч писался для другой платы;
  • общий GND между экраном и контроллером.

Подсветка не светится, картинка вроде есть

Проверьте контакт LED/BL. Если он не подключён, подсветка выключена, и изображение можно разглядеть только под ярко направленным светом под углом. Подключите BL к питанию.

Картинка сдвинута, у края полоса

Неверный таб инициализации. Переберите варианты initR() из таблицы выше.

Красный и синий поменялись местами

Порядок цветовых каналов панели. Попробуйте другой таб или setRGB().

Экран работает, но медленно перерисовывается

Убедитесь, что используется аппаратный SPI, а не программный. При создании объекта Adafruit_ST7735(CS, DC, RST) библиотека сама использует аппаратный SPI. Конструктор с явной передачей MOSI и SCK включает медленный программный SPI — избегайте его без необходимости.

Модуль 80×160 показывает мусор

Используйте INITR_MINI160x80. У этих панелей другое начальное смещение окна, и обычные табы 128×160 не подходят.

Что запомнить

  • ST7735 — SPI-дисплей. Подписи SDA/SCL на плате означают MOSI и SCK, а не I2C.
  • Для работы нужны пять сигналов: SCK, SDA, CS, DC, RST, плюс питание и подсветка.
  • Дешёвые модули — 3,3-вольтовые. Для Uno/Nano либо модуль с поддержкой 5 В, либо преобразователь уровней. Для ESP32 — прямое подключение к 3V3.
  • Для Uno удобно: CS=10, DC=9, RST=8, MOSI=11, SCK=13. Для ESP32: CS=5, DC=2, RST=4, MOSI=23, SCK=18.
  • Белый экран — почти всегда ошибка в подключении или в #define пинов.
  • Сдвиг картинки и полосы по краям лечатся подбором initR()-таба: BLACKTAB, GREENTAB, REDTAB, 144GREENTAB, MINI160x80.
  • Перепутанные красный и синий — особенность порядка каналов панели, а не поломка.
  • Кириллица требует собственного GFX-шрифта; штатный шрифт — только ASCII.
  • microSD на том же модуле спокойно делит SPI с экраном через отдельный CS.

Проверь себя

  1. На плате дисплея есть контакты SDA и SCL. Значит ли это, что экран подключается по I2C?
  2. Экран светится белым, но ничего не показывает. Какие две самые частые причины?
  3. Рамка из тестового скетча обрезана справа, а слева видна цветная полоса. Что нужно поменять в коде?
  4. Почему для дешёвого 3,3-вольтового модуля не стоит напрямую подключать сигналы от Arduino Uno?
Показать ответы
  1. Нет. У ST7735 только SPI. SDA на плате — это линия данных SPI (MOSI), SCL — тактовый сигнал (SCK). I2C-адреса у экрана нет, и I2C-сканер его не найдёт.
  2. Первая — ошибка в подключении или в #define пинов, особенно перепутанные DC и RST. Вторая — отсутствие общего GND или питания. Сама белая подсветка говорит, что питание и LED в порядке, проблема в сигнальных линиях.
  3. Выбран неверный вариант инициализации. Нужно перебрать табы initR(): для 1,8" попробовать INITR_BLACKTAB, INITR_GREENTAB и INITR_REDTAB, пока рамка не встанет ровно по краям.
  4. Логика Uno работает на 5 В, а входы дешёвого модуля рассчитаны на 3,3 В. Прямое подключение выходит за спецификацию чипа и может привести к нестабильной работе или повреждению. Нужен модуль с подтверждённой поддержкой 5 В либо преобразователь уровней.

Источники