OLED дисплей + ChipKit MAX32
Автор: Юрис Гризанс, 2014
Возникла необходимость в небольшом жидкокристаллическом дисплее. В одном Интернет магазине нашел просто изумительный вариант[1]. Во-первых, продукт в виде модуля со штыревым разъемом, что облегчает работу. Во-вторых, всего за 5 долларов. В результате купил сразу три штуки. Однако, подключив устройство, убедился в тезисе, что наличие официального описания не гарантирует приятной и легкой работы. В процессе освоения всплыли различные мелкие нюансы, без учета которых положительного результата не получить. Вот об этом я в статье и расскажу.
Для начала сам модуль OLED2864:
- контроллер SSD1306;
- физический размер 35,5x35,5мм2;
- разрешающая способность самого экрана 128х64;
- напряжение питание 3,3В;
- по умолчанию модуль предназначен для шины I2C (есть возможность использовать SPI, но для этого придется поработать паяльником);
- на плате смонтированы различные дискретные элементы, что дает преимущества, описанные ниже (к сожалению, схемы раздобыть не удалость, поэтому о назначении части компонентов можно только гадать).
На домашней странице магазина можно скачать краткое описание модуля и оригинальное описание контроллера.
Сначала о несуразностях в описании модуля и выявленных особенностях его применения. В таблице указаны выводы, описание которых требует уточнения.
Номер вывода |
Обозна-чение на плате |
Оригинальное описание |
Коррекция |
1 |
VCC |
Voltage at the common collector |
На самом деле это „VDD” (3,3B). Напряжение „VCC” (7 – 15V) генерирует сам контроллер с помощью размещенных на плате конденсаторов. |
3 |
CS |
Chip selection pin |
При использовании протокола I2C, который включен по умолчанию, значение этого сигнала НЕ ИМЕЕТ значения. Вывод можно подключить как к GND так и к питанию – результат будет одинаковый. |
5 |
D/C |
Data/command selection pin |
А вот этот вывод как раз и позволяет выбрать модуль (для I2C). Если вывод соединен с землей, то устройство отзывается на адрес 0х3С. А если соединить с питанием – то 0x3D. |
В результате получается следующая схема (используется шина I2C). К MAX32 сигнал RES можно подключать к любому свободному выводу (только при этом необходимо внести изменения в программе). Стандарт требует, чтобы линии SDA и SCL были соединены с питанием через подтягивающие резисторы. В данном случае они уже размещены на плате дисплейного модуля. Также на плате есть фильтрующие конденсаторы линии питания.
Часть оригинального описания контроллера доступна на русском языке [2].
Продавец предлагает также готовые библиотеки, но у меня они сразу не пошли. Возиться с этой проблемой мне не хотелось, и я решил реализовать весь процесс самостоятельно. Для работы шины используется стандартная библиотека Wire, так что программа, в принципе, должна работать и на других Arduino платах. ТОЛЬКО надо помнить, что подавать на входы дисплейного модуля 5В категорически нельзя (таким образом, может потребоваться согласующее логические уровни устройство).
В описании приводиться рисунок, поясняющий работу шины. Но если четко следовать рекомендации, то дисплей вообще не подает признаков жизни.
Экспериментально был найден скорректированный алгоритм (как иногда бывает, прорыв случился после прочтения буквально двух предложений на форуме). В общих чертах его можно описать как: сброс – начальная инициализация – вывод других команд и данных. Для формирования изображения в программе создан массив данных:
byte Ekran [128][8]
Т.е. в какой-то момент времени программа просто копирует его содержание в память дисплея. Это особенно удобно (для меня) на стадии разработки.
Итак, всю отправляемую в дисплей информацию можно разделить на два вида: команды (управляют работой) и данные (записывают в память изображение). Любая отправка начинается с сигнала СТАРТ и адреса, которые генерирует команда:
Wire.beginTransmission(0х3С)
Все отправленные после адреса байты контроллер воспримет как управляющие команды. За исключением числа 0x40 (16-ричный код), которое контроллер воспринимает его как «контрольный байт», указывающий на то, что следующими байтами пойдут данные. Но здесь надо учесть, что после примерно 40-го байта вывод прекращается. Поэтому для передачи данных можно написать простой цикл, который отправляет по одному байту за сессию (довольно медленный процесс):
for (int y=0; y<=7; y++) { for (int x=0; x<=127; x++) { Wire.beginTransmission(Disp_adr); Wire.send (0x40); Wire.send(Ekran[x][y]); Wire.endTransmission(); } }
Либо группировать вывод, например, по 20 байтов за одну сессию.
for (int y=0; y<=7; y++) { Wire.beginTransmission(Disp_adr); Wire.send (0x40); for (int x=0; x<=20; x++) { Wire.send(Ekran[x][y]); } Wire.endTransmission(); Wire.beginTransmission(Disp_adr); Wire.send (0x40); for (int x=21; x<=40; x++) { Wire.send(Ekran[x][y]); } Wire.endTransmission(); }
Если после вывода данных необходимо снова передать команды (напр., для организации прокрутки изображения), то надо просто открыть новую сессию без передачи контрольного байта.
К статье прилагается пример программы для ChipKit MAX32 (среда mpide, но можно смотреть и в текстовом редакторе).
Ссылки:
1) iMall. http://imall.iteadstudio.com/im130625003.html
2) Драйвер OLED SSD1306. http://catcatcat.d-lan.dp.ua/shemotehnika/oled-displei/drayver-oled-ssd1306/