Если зайти на eBay и ввести в поиске «ST7735», можно найти немало модулей с дисплеем на базе данного контроллера. Модули обычно бывают двух типов — с TFT-дисплеем диагональю 1.44″ и разрешением 128 x 128 пикселей, а также с диагональю 1.8″ и разрешением 128 x 160 пикселей. Последние в большинстве случаев также имеют и разъем для подключения SD-карт . Дисплеи позволят отображать 65536 цветов в палитре R5G6B5. Интересны данные модули тем, что будучи чуть-чуть дороже популярных 0.96-дюймовых OLED-экранчиков на базе SSD1306 предлагают существенно большие разрешение и диагональ, а также в ~30 тысяч раз больше цветов.

Fun fact! Еще есть шилд для Arduino от Duinopeak с 1.8-дюймовым дисплеем, джойстиком и разъемом для SD-карт, а также шапка для Raspberry Pi от WaveShare с 1.44-дюймовым дисплеем, джойстиком и тремя кнопками . Однако цена этих модулей с учетом доставки относительно высока. Кроме того, на AliExpress доступны укороченные 0.96-дюймовые модули с разрешением 80 x 160.

Модули питаются от 3.3 В или 5 В, имеют подсветку (которая питается только от 3.3 В , благодаря чему ее легко случайно спалить !) и используют SPI-подобный протокол. Желающие посмотреть на конкретные единички и нолики протокола, могут воспользоваться Sigrok и соответствующим .sr файлом из репозитория sigrok-dumps . Также мной был написан простенький декодер протокола ST7735 для Sigrok, но на момент написания этих строк патч еще не был вмержен в основную ветку (UPD: как оказалось, на самом деле он уже вмержен, см раз и два ).

В PulseView протокол выглядит как-то так:

Протокол ST7735 в PulseView

Команды и данные передаются с помощью пинов SCLK и MOSI, с порядком бит msb-first, как в обычном SPI. Здесь байт B1 является кодом команды FRMCTR1, а байты 01, 2C и 2D — аргументами этой команды. Отличить аргументы от команды можно по пину DC (data or command), который имеет низкое напряжение для команд и высокое для данных. Также можно заметить, что CS (chip select) можно смело менять посреди передачи фрейма. Как и в традиционном SPI, чип выбран, когда напряжение на CS низкое. Наконец, пин RES позволяет сбросить состояние контроллера, подав на этот пин низкое напряжение.

Для получения приведенной выше картинки я использовал Arduino Uno и библиотеку для ST7735 от Adafruit . В версиях этой библиотеки старше 1.0.8 также вкорячили поддержку ST7789, с иерархиями классов, обмазкой всего макросами, и всяким таким. Из-за этого код библиотеки стал намного труднее для восприятия. Любопытно, что ST7789 не является слишком уж распространненым контроллером. Он похож на ST7735, но в виде модуля продается только в магазине Adafruit за сравнительно большие деньги. Модуль имеет разрешение 240 x 240 при диагонали 1.54″. В своих проектах я бы не стал использовать этот модуль из-за небольшой диагонали, высокой стоимости и завязки на одного производителя. А для изучения работы интересного мне ST7735 я использовал тэг 1.0.8 библиотеки.

Было решено спортировать библиотеку от Adafruit на STM32. Конечно, под STM32 нашлись и готовые библиотеки. Но, во-первых, использование готового кода — это скучно 🙂 Во-вторых, оно не приводит к появлению нормального понимания работы устройства. Наконец, в-третьих, библиотеки, которые мне удалось найти, были написаны хардкорными бородатыми эмбеддерами, привыкшими делать все напрямую через регистры и бинарные сдвиги. Не будучи хардкорным бородатым эмбеддером, я предпочитаю библиотеки без преждевременных оптимизаций, основанные на HAL, которые легче в поддержке и расширении.

Интерфейс библиотеки вышел следующим:

void init ( ) {
ST7735_Init ( ) ;
}

void loop ( ) {
// Check border
ST7735_FillScreen ( ST7735_BLACK ) ;

for ( int x = 0 ; x < ST7735_WIDTH ; x ++ ) {
ST7735_DrawPixel ( x , 0 , ST7735_RED ) ;
ST7735_DrawPixel ( x , ST7735_HEIGHT 1 , ST7735_RED ) ;
}

for ( int y = 0 ; y < ST7735_HEIGHT ; y ++ ) {
ST7735_DrawPixel ( 0 , y , ST7735_RED ) ;
ST7735_DrawPixel ( ST7735_WIDTH 1 , y , ST7735_RED ) ;
}

HAL_Delay ( 3000 ) ;

// Check fonts
ST7735_FillScreen ( ST7735_BLACK ) ;
ST7735_WriteString ( 0 , 0 , «Font_7x10» , Font_7x10 ,
ST7735_RED , ST7735_BLACK ) ;
ST7735_WriteString ( 0 , 3 * 10 , «Font_11x18» , Font_11x18 ,
ST7735_GREEN , ST7735_BLACK ) ;
ST7735_WriteString ( 0 , 3 * 10 + 3 * 18 , «Font_16x26» , Font_16x26 ,
ST7735_BLUE , ST7735_BLACK ) ;
HAL_Delay ( 2000 ) ;

// Check color inversion
ST7735_InvertColors ( true ) ;
HAL_Delay ( 2000 ) ;
ST7735_InvertColors ( false ) ;
HAL_Delay ( 2000 ) ;

// Display test image
ST7735_DrawImage ( 0 , 0 , ST7735_WIDTH , ST7735_HEIGHT ,
( uint16_t * ) test_img_128x128 ) ;
HAL_Delay ( 15000 ) ;
}

Пример вывода текста на дисплей с диагональю 1.44″:

STM32 и ST7735: пример вывода текста

Интересно, что если в случае SSD1306 можно было спокойно хранить всю картинку в памяти и каждый раз передавать ее дисплею целиком, то в случае с ST7735 этого уже так просто сделать нельзя. Тут и цвет 16-и битный, а не монохромный, да и разрешение в 2-2.5 раза выше. Чтобы хранить картинку в памяти микроконтроллера, понадобится 32 Кб для дисплея 128 x 128 и 40 Кб для дисплея 128 x 160. Тем временем, какой-нибудь STM32F103C8T6, используемый в Blue Pill , имеет всего 20 Кб RAM. Конечно, используемый в Nucleo-F411RE микроконтроллер STM32F411RET6 имеет уже 128 Кб RAM. Но мне хотелось бы, чтобы библиотека работала на любом микроконтроллере, и желательно без хаков типа использования 4-х битной палитры, уменьшения разрешения или использования индексированных цветов. Поэтому, в отличие от библиотеки для SSD1306, библиотека для ST7735 сразу отправляет все данные дисплею и ничего не хранит в памяти.

В первом приближении, это все, о чем я хотел сегодня рассказать. Желающие ознакомиться с полной версией кода к этой заметке могут найти его на GitHub . Код работает с дисплеями, имеющими разрешение 80 x 160, 128 x 128 и 128 x 160 пикселей, требуется лишь немного подправить файл st7735.h в соответствии с комментариями в нем. Наиболее же полную информацию о ST7735 вы найдете в даташите [PDF] .

Дополнение: Вас также может заинтересовать статья Использование TFT-дисплеев на базе ILI9341 с тачскрином .

EnglishRussianUkrainian