Как преобразовать spi в oled

Обновлено: 06.07.2024

Микроконтроллеры STM32: работа с OLED-экранчиками на базе SSD1306 по I2C и SPI

Ранее в статье Микроконтроллеры STM32: работа с экранчиком 1602 по I2C мы научились выводить текст на HD44780-совместимый ЖК-индикатор с I2C-адаптером на базе чипа PCF8574. Эти индикаторы хороши тем, что они не дороги, имеют подсветку и позволяют выводить крупный текст. Но при этом они не могут похвастаться большой скоростью перерисовки, широким углом обзора, или возможностью выводить графическую информацию. Плюс к этому, они довольно громоздки, что в определенных задачах может быть неудобно. Поэтому сегодня мы поговорим о популярных OLED-дисплеях на базе чипа SSD1306, лишенных названных недостатков.

Fun fact! В этом блоге OLED-экранчик с I2C-интерфейсом на базе SSD1306 ранее уже упоминался в статье Используем джойстик от Sega Genesis в проектах на Arduino.

Соответственно, дисплеи обычно продаются в виде I2C- или SPI-модулей, имеющих пины с шагом 2.54 мм. Но также продаются и дисплеи без какой-либо обвязки, имеющие только шлейф, идущий непосредственно к чипу. Интересно, что SPI-модули обычно имеют шелкографию, объясняющую, как перепаять их в I2C-модуль или модуль, работающий по 3-wire SPI. Например, я вполне успешно перепаял вот такой SPI-модуль от WaveShare, чтобы он работал по I2C. Увы, чтобы переделанный модуль работал корректно, ему приходится подавать на пин Reset сначала низкое напряжение, а затем высокое, что не требуется в обычных I2C-модулях. Но в остальном он работает без нареканий.

Пример работы микроконтроллера STM32 с OLED-экранчиком на базе SSD1306 по I2C

Было протестировано несколько библиотек для работы с такими экранчиками. В итоге, больше всего мне понравилась 4ilo/ssd1306-stm32HAL. Позже я выяснил, что ее Google и выдает первой по запросу «stm32 ssd1306 library». Библиотека отличная, заводится с пол-оборота, содержит всего 150 строк кода, работает без нареканий. К сожалению, она умеет работать только по I2C. Поэтому поддержку SPI мне пришлось дописать самостоятельно, ну и заодно отрефачить кое-что по мелочи. Ссылку на получившуюся в итоге библиотеку ищите в конце поста.

В ходе работы над библиотекой я узнал, что дисплей 1.3" почему-то немного иначе адресует пиксели, чем дисплей 0.96". Чтобы на нем все отображалось корректно, мне пришлось переопределить ширину экрана:

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

Полную версию кода вы найдете на GitHub. Узнать больше о чипе SSD1306 можно из его даташита [PDF].

Библиотека была протестирована только на микроконтроллерах семейства STM32F1 и STM32F4, так как других у меня под рукой попросту нет. Если вас не затруднит проверить ее на других микроконтроллерах и сообщить о результатах в комментариях, я был бы крайне признателен. Также прямо сейчас у меня нет возможности проверить, работает ли библиотека с экранчиками на базе SH1106 и SSD1309. Если вы можете протестировать это, мне также крайне хотелось бы узнать о результатах. Наконец, отмечу, что я с радостью приму патчи, добавляющие в библиотеку, скажем, вывод геометрических фигур, русские шрифты или поддержку 3-wire SPI.

А что вы думаете о подобных OLED-экранчиках? Доводилось ли вам с ними работать? Если да, то какую библиотеку вы использовали, и по какому протоколу она говорила с дисплеем?

Вывод информации из микроконтроллера зачастую создаёт больше сложностей, чем непосредственно работа основной программы – ведь необходимо и “отдать” несколько пинов для подключения, и некоторое количество памяти для библиотеки обработки графики.

Новички часто допускают ошибку, либо пытаясь запихнуть большое количество данных на маленький экран (вроде Nokia 3310), либо наоборот – в любой, даже самый маленький проект добавляют гигантский дисплей, требующий большой производительности.

Мы рассмотрим компромиссное решение – небольшой по размеру (0.96”), но с достаточным разрешением (128×64) экран с подключением всего по 3 проводам!

Обзор модуля

OLED 128x64px SPI - схема подключения к Arduino

SSD1306 – контроллер, на котором построено несколько вариаций дисплейных модулей. Часто встречаются также подключающиеся по интерфейсу I²C, но наш сегодняшний вариант подключается по более скоростному SPI.

Сам дисплей, установленный на модуле, выполнен по технологии OLED, что гарантирует низкое потребление, высокую скорость переключения (как следствие, большая возможная частота обновления экрана). Экран двухцветный, что не позволяет выводить точные картинки, зато помогает снизить размер буфера для видеопамяти всего до 1 Кб, так как 8 точек кодируются сразу одним байтом.

Подключение по SPI обеспечивает скорость соединения до 20 Мбит/с, с чем интерфейс I²C с его запросами и сложной структурой конкурировать неспособен. Доступно также подключение по параллельным интерфейсам, но модули с таким подключением мало распространены.

Питание модуля – 3.3 В, но на плате установлен стабилизатор с низким падением напряжения, что позволяет питать дисплей как от 5 В, так и от 3.3 В напрямую. Лучше использовать 5 В питание – этим вы разгружаете и без того не сильно мощный 3.3 В стабилизатор, установленный на Arduino.

Максимальное потребление (когда включены все пиксели дисплея) порядка 20 мА, поэтому при необходимости его можно питать прямо от пина микроконтроллера.

Схема подключения к Arduino

OLED 128x64px SPI - схема подключения к Arduino

  • CS – любой пин Arduino
  • SCK – 13 пин (Arduino UNO)
  • MOSI – 11 пин
  • Vcc – 3.3…5В
  • GND – GND

Распиновку интерфейса для других плат можно найти на официальном сайте.

Подключение в Arduino IDE

Для дисплея существует множество библиотек, причём никто не запрещает вам написать свою – протокол описан в даташите. Но для упрощения задачи мы возьмём готовую библиотеку U8gLib. Она поддерживает большое количество контроллеров экрана, в числе которых и SSD1306.

Откройте любой пример. В начале скетча будет большое количество закомментированных строк инициализации для разных контроллеров. Найдите среди них SSD1306, подключающийся по SPI и имеющий разрешение 128×64, после чего раскомментируйте эту строчку и можете загружать скетч!


Надоело использовать символьные ЖК-дисплей в своих проектах Arduino? Что ж! Они действительно уходят в прошлое. Используйте в своих проектах современные OLED (органические светодиоды) дисплеи! Они легкие, тонкие, теоретически гибкие и дают более яркое и четкое изображение.

Модуль OLED диспля на основе драйвера SSD1306

В основе модуля лежит мощный однокристальный CMOS контроллер SSD1306. Он может общаться с микроконтроллером несколькими способами, включая I2C и SPI .

Протокол SPI, как правило, быстрее, чем I2C, но требует большего количества контактов ввода/вывода микроконтроллера. В то время как I2C требует только два контакта и может использоваться совместно с другими периферийными устройствами I2C. Это компромисс между экономией выводов и скоростью.



Требование к источнику питания

Для работы OLED-дисплею не нужна подсветка, поскольку он излучает свой собственный свет. Именно поэтому дисплей имеет такой высокий контраст, чрезвычайно широкий угол обзора и может отображать глубокий уровень черного цвета.

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

Рабочее напряжение контроллера SSD1306 составляет от 1,65 до 3,3 В, в то время как для OLED-панели требуется напряжение питания от 7 до 15 В. Все эти различные требования к питанию решаются путем использования схемы Charge Pump. Это позволяет легко подключить модуль к Arduino или любому 5-вольтовому логическому микроконтроллеру без использования преобразователя логического уровня.

Организация памяти SSD1306

Независимо от размера OLED модуля драйвер SSD1306 имеет встроенную память объемом 1 КБ (GDDRAM). Эта область памяти разбита на 8 страниц (от 0 до 7). Каждая страница содержит 128 столбцов / сегментов (блок от 0 до 127). И каждый столбец может хранить 8 бит данных (от 0 до 7):

8 страниц x 128 сегментов x 8 бит данных = 8192 бит = 1024 байт = 1 Кб памяти

Организация памяти SSD1306

Каждый бит представляет собой определенный OLED пиксель на экране, который может быть включен или выключен программно.

Экран 128 × 64 OLED отображает все содержимое ОЗУ, тогда как экран 128 × 32 OLED отображает только 4 страницы (половину содержимого) ОЗУ.

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

Прежде чем перейти к написанию кода и рассмотрению примеров, давайте сначала посмотрим на распиновку OLED модуля:

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

Подключение модуля OLED к Arduino Uno

Прежде чем мы перейдем к загрузке кода и отправке данных на дисплей, давайте подключим дисплей к Arduino Uno .

Схема подключения довольно проста. Начните с подключения контакта VCC к выходу 5V на Arduino и GND к земле. Теперь остались выводы, которые используются для связи по I2C. Обратите внимание, что каждая плата Arduino имеет разные контакты I2C.

На платах Arduino с маркировкой R3 SDA (линия передачи данных) и SCL (линия синхронизации) находятся на разъемах рядом с выводом AREF. Они также известны как A5 (SCL) и A4 (SDA).

Если у вас MEGA , контакты будут другие! Используйте цифровые 21 (SCL) и 20 (SDA).

линии I2C для различных Arduino

На следующей схеме показано как все должно быть подключено:

Подключение модуля OLED к Arduino Uno

Установка библиотеки для модуля OLED

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

Чтобы установить библиотеку, перейдите в раздел Sketch > Include Library > Manage Libraries…. Подождите, пока менеджер библиотеки загрузит индекс библиотек и обновит список установленных библиотек.

 библиотека Adafruit SSD1306

Отфильтруйте результаты поиска, введя adafruit ssd1306. Там должна быть пара записей. Ищите Adafruit SSD1306 от Adafruit. Нажмите на эту запись, а затем выберите Установить.


Библиотека Adafruit SSD1306 представляет собой аппаратную библиотеку, которая выполняет функции более низкого уровня. Она должна быть сопряжена с библиотекой Adafruit GFX для отображения графических примитивов, таких как точки, линии, круги, прямоугольники и т. д. Также установите и эту библиотеку.

 библиотека Adafruit GFX

Известная проблема с контроллером SSD1306

Хотя SSD1306 имеет встроенный GDDRAM для экрана, мы не можем прочитать его содержимое (согласно Adafruit). Следовательно, невозможно управлять экранным буфером для выполнения математических операций.

В качестве альтернативы библиотека выделяет 1 КБ (128 × 64) / 8 бит) памяти ATmega328P в качестве буфера. Таким образом, появляется возможность манипулировать экранным буфером и затем выполнять массовую передачу из памяти ATmega328P во внутреннюю память контроллера SSD1306.

Модификация библиотеки Adafruit SSD1306

Библиотека Adafruit SSD1306 не настроена для 128 × 64 OLED-дисплеев (используемый в данной статье). Размер экрана необходимо изменить в заголовочном файле Adafruit_SSD1306.h.

Чтобы изменить заголовочный файл Adafruit_SSD1306.h, откройте Документы > Arduino. Теперь перейдите в библиотеку Adafruit_SSD1306:

Модификация библиотеки Adafruit SSD1306

редактирование библиотеки

Вот и все. Теперь сохраните файл и перезапустите вашу Arduino IDE.

Скетч для отображения текста на OLED

Теперь самое интересное!

  • Отображение перевернутого текста
  • Отображение номеров
  • Отображение чисел (Hex, Dec)
  • Отображение ASCII символов
  • Прокрутка текста по горизонтали и вертикали
  • Прокрутка части дисплея

Это даст вам полное представление о том, как использовать OLED-дисплей, и может послужить основой для реализации своих проектов.

При компиляции кода в среде IDE появиться предупреждение о нехватке памяти. Это связано с тем, что библиотека выделяет 1 КБ памяти ATmega328P в качестве буфера отображения. Вы можете игнорировать это.

Скетч начинается с подключения четырех библиотек, а именно. SPI.h, Wire.h, Adafruit_GFX.h и Adafruit_SSD1306.h. Хотя библиотека SPI.h не требуется для I2C OLED-дисплеев, нам нужно добавить ее для компиляции нашей программы:

Далее нам нужно создать объект Adafruit_SSD1306.h. Конструктор Adafruit_SSD1306 принимает номер контакта Arduino, к которому подключен вывод сброса дисплея. Поскольку используемый нами OLED-дисплей не имеет вывода RESET, мы отправим в конструктор -1 , чтобы ни один из выводов Arduino не использовался в качестве сброса для дисплея.

В функции setup() нам нужно инициализировать объект OLED с помощью функции begin(). Функция принимает два параметра. Первый параметр SSD1306_SWITCHCAPVCC включает схему charge pump, а второй параметр устанавливает адрес I2C OLED дисплея. I2C адрес такого OLED модуля обычно равен 0x3C.

Отображение простого текста (Hello World)


Для отображения текста на экране нам нужно установить размер шрифта. Это может быть сделано путем вызова setTextSize() и передачи размера шрифта (начиная с 1) в качестве параметра.

Пиксели на экране адресуются по горизонтальным (X) и вертикальным (Y) координатам. Система координат размещает начало координат (0,0) в верхнем левом углу, причем положительный X увеличивается вправо, а положительный Y увеличивается вниз.

Чтобы библиотека могла выполнять чрезвычайно быстрые математические операции с буфером экрана (более 100 кадров в секунду), вызовы функций печати не сразу передают содержимое экранного буфера в SSD1306 контроллер.

Для этого требуется команда display(), чтобы дать указание библиотеке выполнить массовую передачу из экранного буфера ATmega328P во внутреннюю память контроллера SSD1306. Как только память будет перенесена, на OLED-дисплее появятся пиксели, соответствующие экранному буферу.


Для выполнения инверсии мы снова вызываем функцию setTextColor(FontColor,BackgroundColor). Если вы обратили внимание, то вы заметите, что до этого мы передали только один параметр этой функции, но теперь мы передаем два параметра.

Изменение размера шрифта


Ранее мы вызывали функцию setTextSize() для установки размера шрифта и передавали 1 в качестве параметра. Вы можете использовать эту функцию для масштабирования шрифта, передавая любое неотрицательное целое число.

Символы отображаются в соотношении 7:10. Это означает, что при передаче размера шрифта 1 текст будет отображаться с разрешением 7 × 10 пикселей на символ, при передаче 2 будет отображаться текст с разрешением 14 × 20 пикселей на символ и т. д.

Отображение чисел


Числа могут быть отображены на OLED дисплее путем вызова функций print() или println().

Указание базиса чисел

Указание базиса чисел

Функции print() и println() имеет второй необязательный параметр , который определяет базу (формат). Допустимые значения:

  • BIN (двоичное или базовое 2),
  • OCT (восьмеричное или базовое 8),
  • DEC (десятичное или базовое 10),
  • HEX (шестнадцатеричное или базовое 16).

Для чисел с плавающей запятой этот параметр указывает количество десятичных знаков. Например:

Отображение ASCII символов


Функции print() и println() отправляют данные на дисплей в виде удобочитаемого текста ASCII, а функция write() отправляет двоичные данные. Таким образом, вы можете использовать эту функцию для отображения символов ASCII. В нашем примере отправка числа 3 будет отображать символ сердца.

Полноэкранная прокрутка

Вы можете прокручивать дисплей по горизонтали, вызывая функции startscrollright() и startscrollleft(), и по диагонали, вызывая startscrolldiagright() и startscrolldiagleft(). Все эти функции принимают два параметра, а именно: начальная страница и конечная страница.

Поскольку на дисплее отображается восемь страниц от 0 до 7, вы можете прокручивать весь экран, прокручивая все страницы, то есть передавая параметры 0x00 и 0x07. Чтобы остановить отображение прокрутки вы можете использовать функцию stopscroll().

Прокрутка определенной части

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

Поскольку на дисплее отображается восемь страниц от 0 до 7, мы можете прокрутить некоторую часть экрана, передавая конкретные номера страниц в качестве параметров.

В нашем примере мы передали оба параметра как 0x00. Это позволит прокрутить только первую страницу (первые 8 строк) дисплея.

В этом примере рассмотрим некоторые базовые фигуры. Этот скетч демонстрирует множество функций рисования, включая прямоугольник, скругленный прямоугольник, круг и треугольник.

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

Рисование прямоугольника



Вы можете нарисовать на дисплее прямоугольник с помощью функции drawRect(). Функция принимает пять параметров, а именно: координаты X и Y, ширина, высота и цвет. На самом деле эта функция рисует не закрашенный прямоугольник с границей в 1 пиксель. Вы можете нарисовать закрашенный прямоугольник, используя функцию fillRect().

Рисование скругленный прямоугольник



Рисование круга



Вы можете нарисовать круг на дисплее с помощью функции drawCircle(). Функция принимает четыре параметра, а именно: координата центра X и Y, радиус и цвет. Эта функция рисует не закрашенный круг с границей в 1 пиксель. Вы можете нарисовать закрашенный круг, используя функцию fillCircle().

Рисование треугольника



Вы можете нарисовать треугольник на дисплее с помощью функции drawTriangle(). Функция принимает семь параметров, а именно: X и Y координаты (x0, y0, x1, y1, x2, y2) вершин треугольника и цвета. (x0, y0) представляет верхнюю вершину, (x1, y1) представляет левую вершину и (x2, y2) представляет правую вершину.

Эта функция рисует не закрашенный треугольник с границей в 1 пиксель. Вы можете нарисовать закрашенный треугольник, используя функцию fillTriangle().

Мы уже познакомились с разными видами дисплеев, включая популярный символьный 1602 и не менее популярный графический ЖК дисплей от телефона Nokia 5110. Они хороши для решения своих утилитарных задач. На первом можно легко вывести показания различных датчиков, и организовать меню настройки какого-нибудь прибора. На втором дисплее, от Nokia 5110, можно рисовать графики, геометрические фигуры, даже вывести черно-белую картинку.

Сегодня речь пойдет еще об одном типе цифровых индикаторов, которые основаны на технологии OLED. В отличие от ЖК дисплеев, в OLED каждый пиксель изображения светится сам, что делает ненужным подсветку. По сути, OLED матрица состоит из множества органических светодиодов. Благодаря таким светящимся пикселям, эти дисплеи обладают запредельными показателями контрастности. А еще, OLED технология позволяет делать гибкие матрицы!

DSC00905_sm

Раз OLED дисплей такой хороший, попробуем его подключить к Ардуино, и увидеть все своими глазами!

1. Подключение OLED дисплея к Ардуино

Дисплейные модули OLED могут иметь разные интерфейсы для связи с контроллером. В нашем распоряжении оказался модуль с SPI шиной, у которого было распаяно шесть ног:

Схема подключения к Ардуино:

2. Программа. Вывод текста

Для управления дисплеем нам потребуются две библиотеки:

Устанавливаем обе библиотеки в Arduino IDE, и пробуем вывести наш любимый «Hello world!»:

Загружаем программу на Ардуино Уно, и получаем вот такую яркую надпись очень мелким шрифтом:

DSC00907_sm

Подробное описание функций, которые мы использовали в коде, можно найти в предыдущем уроке про Nokia 5110. Там же можно найти описание функций для вывода геометрических фигур.

3. Программа. Вывод изображения

Как и в случае дисплея Nokia 5110, для того чтобы вывести изображение нам необходимо его должным образом подготовить. На всякий случай, напомню алгоритм:

Осталось вставить полученный массив данных в программу:

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

Итак, OLED дисплей побежден!

Задания

Чтобы развить навыки работы с OLED дисплеем, рекомендуем выполнить несколько заданий.

Читайте также: