Библиотека TFT на ATtiny85, управляющая цветным дисплеем Adafruit 2.0" 320x240

В статье речь пойдёт о маленькой графической библиотеке, предназначенной специально для микроконтроллеров ATtiny, используемых с различными миниатюрными TFT-дисплеями, которые можно недорого приобрести на сайтах Adafruit, AliExpress или Banggood.

Это обновлённая версия моей Tiny TFT Graphics Library, которая поддерживает и классические процессоры ATtiny, такие как ATtiny85, и новые модели 0-, 1- и 2-серий, например, ATtiny402. Как и оригинальная библиотека, она позволяет отрисовывать точки, линии, закрашенные прямоугольники, а также символы и текст в 16-битной цветовой палитре с настраиваемым фактором масштабирования.

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

Введение


Эта библиотека поддерживает TFT-дисплеи, использующие интерфейс SPI и требующие четыре контакта для управления. В итоге на 8-контактной микросхеме вроде ATtiny85 или ATtiny402 остаётся один свободный контакт. Если вам нужно больше, берите другую микросхему, например, ATtiny84 или ATtiny404.

В отличие от моей Compact TFT Graphics Library, которая использует стандартные вызовы Arduino SPI, эта библиотека напрямую взаимодействует с вводом/выводом. Это примерно вдвое ускоряет работу в сравнении с использованием SPI, а также позволяет использовать любое назначение контактов четырёх необходимых дисплею линий ввода/вывода. Ещё я расширил спектр поддерживаемых TFT-дисплеев – теперь их 16.

Как всё это работает


На классических процессорах ATtiny, таких как ATtiny85, библиотека использует возможность переключения одного или более бит в порту с помощью записи в регистр PINB, например, для активации/отключения сигнала chip-select (выбора микросхемы):

PINB = 1<<cs;

Так что, если при запуске все контакты установлены на состояние «отключён», то процедуры дисплея смогут просто переключать нужные из них, активируя или отключая.

На новых ATtiny 0- и 1-серии используется равнозначный регистр OUTTGL. Например:

PORTA.OUTTGL = 1<<cs;

Отличия между каждым семейством процессоров обрабатываются константами, определяющими назначения контактов, и макросом препроцессинга, определяющим манипуляции с битами. Если вы примените приведённые ниже схемы, то вам не потребуется что-либо менять, только указать, какой используется дисплей.

Я дополнительно оптимизировал процедуру ClearDisplay(), когда осознал, что нет нужды продолжать и устанавливать бит mosi, так как для очистки дисплея он всегда будет нулевым, а значит, процедуре нужно только переключать бит sck нужное число раз. Благодарю Томаса Шерера за поданную идею.

Быстродействие


В таблице ниже отражено отличие в быстродействии при использовании TFT-дисплея 240х240 с ATtiny402 20МГц:
  Компактная библиотека TFT Крошечная библиотека TFT
ClearDisplay() 856 мс 279 мс
FillRect(240, 240) 1142 мс 737 мс
TestChart() 210 мс 61 мс
BarChart() 1306 мс 728 мс
Вся библиотека занимает менее 4КБ, включая набор символов и демо-программы, а значит, вполне уместится на микроконтроллерах с 4КБ флэш-памяти, таких как ATtiny45 и ATtiny402.

Поддерживаемые дисплеи


Эта библиотека будет работать с дисплеями на базе контроллера ST7735, поддерживающего максимальный размер экрана 162х132, либо ST7789 и ILI9340/1, поддерживающих размер 320х240. Она содержит параметры для следующих цветных TFT-дисплеев:
Поставщик Размер Ширина Высота Напряжение Контроллер Ссылка
Adafruit 1.44" 128 128 3.3 — 5V ST7735R Adafruit 1.44" Color TFT LCD Display *
AliExpress 1.44" 128 128 3.3 — 5V ST7735R 1.44" 128x128 SPI TFT display †
Adafruit 0.96" 160 80 3.3 — 5V ST7735 Adafruit 0.96" 160x80 Color TFT Display *
AliExpress 0.96" 160 80 3.3V ST7735 TFT Display 0.96 inch 80x160 †
Adafruit 1.8" 160 128 3.3 — 5V ST7735R Adafruit 1.8" Color TFT LCD display
AliExpress 1.8" 160 128 3.3V ST7735R 1.8 inch TFT LCD Module 128x160
AliExpress 1.8" 160 128 3.3V ST7735R 1.8" 128x160 SPI TFT display †
Adafruit 1.14" 240 135 3.3 — 5V ST7789 Adafruit 1.14" 240x135 Color TFT Display *
AliExpress 1.14" 240 135 3.3V ST7789 1.14in SPI 240x135 RGB TFT display †
Adafruit 1.3" 240 240 3.3 — 5V ST7789 Adafruit 1.3" 240x240 Wide Angle TFT LCD Display *
Adafruit 1.54" 240 240 3.3 — 5V ST7789 Adafruit 1.54" 240x240 TFT LCD Display *
AliExpress 1.54" 240 240 3.3V ST7789 1.54" TFT 240x240 LCD Display †
Adafruit 1.9" 320 170 3.3 — 5V ST7789 Adafruit 1.9" 320x170 Color IPS TFT Display *
Adafruit 2.0" 320 240 3.3 — 5V ST7789 Adafruit 2.0" 320x240 Color TFT Display *
Adafruit 2.2" 320 240 3.3 — 5V ILI9340C Adafruit 2.2" 320x240 Color TFT Display
AliExpress 2.4" 320 240 3.3V ILI9341 2.4" 320x240 TFT Display Module †

* Эти дисплеи Adafruit к удобству имеют одинаковое расположение боковых разъёмов, что позволяет собрать макетную или печатную плату с возможностью подключения любого из них.

† Эти модели с AliExpress тоже имеют одинаковое расположение разъёмов. Некоторые из них включают LDO-регулятор 3.3В, но без преобразования логического уровня, так что я советую подключать их только к процессору, работающему от 3.3В.

В свою очередь, дисплеи Adafruit все содержат LDO-регулятор 3.3В и преобразователь логического уровня, а значит, могут подключаться к процессорам 5В или 3.3В.

У красного дисплея 160х128 с AliExpress для включения подсветки её контакт нужно подключить к Vcc. В случае других дисплеев этого не требуется.

Моя библиотека позволяет настраивать ориентацию изображения — чтобы можно было по-разному обыграть установку дисплея.

Есть вероятность, что она будет поддерживать и другие модели с теми же контроллерами ST7735, ST7789 или ILI9340/1, но при этом вам может потребоваться подобрать параметры, чтобы добиться правильного масштабирования и центровки изображения.

Подключение дисплея


Для использования библиотеки нужно правильно подключить дисплей и выбрать для него подходящие параметры.

Дисплей подключается к микроконтроллеру по четырём линиям ввода/вывода: MOSI, SCK, CS и DC. Для этого можно задействовать любые контакты, но они все должны находиться в одном порту. Номера используемых контактов порта необходимо указать в начале листинга библиотеки.

Имейте ввиду, что на разных платах дисплеев контакты обозначаются по-разному:
Контакт Маркировка
Vcc Vin
Ground GND
Clock SCK, SCL
Data In MOSI, SI, SDA
Chip Select CS, TCS
Data/Command DC, D/C, A0
Backlight LITE, LIT, BLK
Не удивляйтесь используемой на некоторых дисплеях маркировке SCL и SDA — это определённо дисплеи SPI.

ATtiny85/45


По умолчанию библиотека устанавливает для ATtiny85/84 следующие контакты в PORT B:

int const dc = 0;
int const mosi = 1;
int const sck = 2;
int const cs = 3;

А вот соответствующая схема подключения дисплея с AliExpress:

Схема подключения цветного TFT-дисплея с использованием ATtiny85

Подтягивающий резистор 33кОм здесь необязателен. Он необходим только на дисплеях с AliExpress, где его задача удерживать chip select на высоком уровне, чтобы во время программирования микроконтроллера экран не мерцал.

В случае дисплеев Adafruit можно обойтись без резистора 10кОм, поскольку у них подтягивание реализовано на собственной плате.

ATtiny402/412


По умолчанию библиотека устанавливает для ATtiny402/412 следующие контакты в PORT A:

int const dc = 7;
int const mosi = 1;
int const sck = 3;
int const cs = 6;

А вот соответствующая схема подключения дисплея с AliExpress:

Схема подключения цветного TFT-дисплея с использованием ATtiny402

При использовании дисплея Adafruit резистор 10кОм можно опустить, так как у них подтягивание происходит на самой плате.

Пример реализации этой схемы с дисплеем Adafruit 320x240 2.2" TFT:

Крошечная библиотека TFT на ATtiny402, управляющая цветным TFT-дисплеем Adafruit 2.2" 320x240

Настройка дисплея


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

// Adafruit 1.44" 128x128 display
int const xsize=128, ysize=128, xoff=2, yoff=1, invert=0, rotate=3, bgr=1;

Раскомментируйте параметры для используемого дисплея.

По умолчанию параметры задают верную ориентацию — исходя из предположения, что вы используете контакты вдоль верхней части дисплея. Исключением становятся крупные модели, у которых эти контакты расположены вдоль короткой стороны – в этом случае предполагается, что они находятся слева.

Тем не менее изменяя константу rotate, можно настроить поворот экрана по-своему:

Тестовый паттерн Test Chart

Имейте в виду, что на некоторых дисплеях при повороте изображения вам также может потребоваться изменить значение xoof или yoff.

Для проверки или подстройки значений под каждый дисплей можно использовать программу TestChart(), которая рисует по периметру рамку с отступом в один пиксель и отображает “F”, позволяя определить ориентацию:

void TestChart () {
  DrawRect(xsize, ysize);
  scale = 8;
  fore = Colour(255, 0, 0);
  MoveTo((xsize-40)/2, (ysize-64)/2); PlotChar('F');
  scale = 1;
}

Пример:

Test Chart на цветном TFT-дисплее 1.14" 240x135 с AliExpress

Если символ “F” окажется синим, необходимо изменить значение bgr.

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

Графические команды


Вот общий список графических команд библиотеки:

Colour
Библиотека использует 16-битный режим цвета, в котором 5 бит отводится красному, 6 зелёному и 5 синему.

Colour() позволяет задавать значение цвета путём указания его красной, зелёной и синей компонент в виде чисел от 0 до 255:

unsigned int Colour (int r, int g, int b)

Передний и задний план
Цвет переднего и заднего плана определяется двумя глобальными переменными fore и back. Изначально они установлены на белый (0xFFFF) и чёрный (0) соответственно.

int fore = White;
int back = Black;

Очистка дисплея
ClearDisplay() очищает дисплей в чёрный цвет:

void ClearDisplay ()

Нанесение точек и отрисовка линий
Библиотека содержит базовые графические процедуры для нанесения точек и отрисовки линий. Работают они в традиционной системе координат, где исходная точка находится в нижнем левом углу.

Вот пример для дисплея 80х160:



Текущая позиция отрисовки хранится в глобальных переменных xpos и ypos. Изменить её можно с помощью MoveTo():

void MoveTo (int x, int y)

PlotPoint() наносит одну точку, имеющую цвет текущего переднего плана:

void PlotPoint (int x, int y)

DrawTo() отрисовывает линию с цветом переднего плана из текущей позиции до x,y, после чего текущая позиция обновляется:

void DrawTo (int x, int y)

Отрисовка прямоугольников
DrawRect() рисует контурный, а FillRect() закрашенный прямоугольник, с шириной w и высотой h. При этом нижний левый угол устанавливается в текущую позицию отрисовки, а закрашивание производится в текущий цвет переднего плана:

void DrawRect (int w, int h)
void FillRect (int w, int h)

После позиция отрисовки не меняется.

Отрисовка кругов
DrawCircle() рисует контурный, а FillCircle() закрашенный круг с радиусом radius, устанавливая центр в текущую позицию отрисовки:

void DrawCircle (int radius)
void FillCircle (int radius)

По завершению позиция отрисовки остаётся прежней.

Символы и текст
Библиотека содержит набор символов, основанный на точечной матрице 5х7.

PlotChar() отрисовывает заданный символ в текущей позиции с текущим цветом переднего плана:

void PlotChar (char c)

Можно отрисовывать более крупные символы, изменяя переменную scale, чьё изначальное значение равно 1. После отрисовки символа PlotChar() перемещает текущую позицию к началу следующего, позволяя выводить несколько символов подряд без вызова MoveTo().

PlotText() выводит текст из строки, содержащейся в программной памяти:

void PlotText (PGM_P p)

Примеры можно посмотреть в демо-программах.

PlotInt() рисует число:

void PlotInt (int i)

Компиляция графической библиотеки


ATtiny85/45


Скомпилируйте программу с помощью ATTinyCore от Spence Konde. В меню Board под заголовком ATTinyCore выберите опцию ATtiny25/45/85 (No bootloader). Затем убедитесь, чтобы последующие опции были установлены так (прочие игнорируйте):

Chip: "ATtiny85"
Clock Source: "8 MHz (internal)"

По умолчанию ATtiny работает на 1МГц. Выберите Burn Bootloader, чтобы установить фьюз-биты в режим 8МГц, иначе графика будет работать медленно. Затем загрузите программу с помощью программатора ISP, например, Tiny AVR Programmer Board от SparkFun.

ATtiny402/412


Скомпилируйте программу с помощью megaTinyCore от Spence Konde. В меню Board под заголовком megaTinyCore выберите опцию ATtiny412/402/212/202. Проверьте, чтобы последующие опции были установлены так (остальные игнорируйте):

Chip: "ATtiny420" (либо другой соответствующий)
Clock: "20 MHz internal"

Далее загрузите программу через программатор UPDI. Рекомендуется использовать плату USB to Serial, например, FTDI Basic от SparkFun, подключённую через резистор 4.7кОм:



Установите опцию Programmer на «SerialUPDI with 4.7k resistor or diode (230400 baud)».

Ресурсы



Комментарии (3)


  1. lab412
    12.06.2022 13:42
    +1

    Шикарно! А можно узнать о производительности? Видео посмотреть как отрисовка с какой скоростью обновление и всё такое. Графики те-же самые с примера. Есть задачи которым и EInk подходит где обновление экрана секунду занимает, а есть нечто вроде эквалайзера или осциллографа


    1. iliasam
      12.06.2022 17:50
      +3

      Это же перевод.


    1. RussianWarShip
      14.06.2022 12:09

      Из программного SPI много не выжмешь, так что о производительности можно забыть.