Как стать автором
Обновить

Общаемся с дисплеем SSD1306 по i2c

Время на прочтение4 мин
Количество просмотров16K

Все любители электронных самоделок когда-нибудь приходят к желанию отобразить работу своей поделки самоделки на экране в виде текста или графики. Самый бюджетный способ сделать это — обратиться к алфавитно-цифровому дисплею типа LCD1602 или LCD2004, общение с которыми происходит либо по параллельному интерфейсу, либо через переходник-конвертор в I2C. Второй способ — использовать графический дисплей, их множество, например SSD1306 с размером матрицы 128x64 пикселя. Он есть в двух вариантах, с интерфейсом SPI или I2C. Я буду взаимодействовать с таким дисплеем через I2C интерфейс (он же TWI).

Рисунок 1.- графический LCD дисплей SSD1306 
с матрицей 128x64 пикселя
Рисунок 1.- графический LCD дисплей SSD1306 с матрицей 128x64 пикселя
  1. Сначала подаем команду старт

  2. Передаем адрес дисплея SLA+W

  3. Дальше идет m слов содержащих всевозможные настройки дисплея

  4. Передается признак того, что дальше пойдут графические данные (1 байт) и собственно данные n байт.

Передача каждого байта устанавливает статус ACK.

Рисунок 2.- формат пакета данных для дисплея
Рисунок 2.- формат пакета данных для дисплея

Инициализация модуля

Вот последовательность действий для инициализации графического дисплея

  1. Отправляем дисплей в SLEEP MODE (команда 0xAE SSD1306_DISPLAYOFF)

  2. Установка делителя частоты (команда 0xD5 SSD1306_SETDISPLAYCLOCKDIV) параметр 0x80

  3. Устанавливает отношение мультиплексирования (команда A8 SSD1306_SETMULTIPLEX) параметр 0x3F

  4. Устанавливаем смещение дисплея (команда 0xD3 SSD1306_SETDISPLAYOFFSET) параметр 0x00

  5. устанавливаем начальную линию (команда 0x40 SSD1306_SETSTARTLINE|0x00)

  6. разрешаем charge pump (команда 0x8d SSD1306_CHARGEPUMP) параметр 0x14

  7. устанавливаем горизонтальный режим памяти (команда 0x20 SSD1306_MEMORYMODE) параметр 0x00.

  8. устанавливаем remapping столбцов seg0←→seg127 (команда 0xA0 SSD1306_SEGREMAP | 0x00)

  9. устанавливаем направление сканирования строк (команда 0xС8 SSD1306_COMSCANDEC)

  10. Устанавливаем конфигурацию выводов COM-сигналов в соответствии с компоновкой оборудования OLED - панели (команда 0xDA SSD1306_SETCOMPINS) параметр 0x12

  11. Устанавливаем контраст (команда 0x81 SSD1306_SETCONTRAST) параметр 0xCF

  12. Установка предзаряда (команда 0xD9 SSD1306_SETPRECHARGE) параметр 0xF1

  13. Установка Vcomp deselect level (команда 0xDB SSD1306_SETVCOMDETECT) параметр 0x40

  14. Возобновление отображения содержимого оперативной памяти (команда 0xA4 SSD1306_DISPLAYALLON_RESUME)

  15. Отображение в нормальном виде команда 0xA6 SSD1306_NORMALDISPLAY

  16. Включение дисплея в нормальном режиме команда 0xAF SSD1306_DISPLAYON

Ниже на рисунке 3 приведена ассемблерная подпрограмма инициализации дисплея

Рисунок 3.- Подпрограмма инициализации дисплея
Рисунок 3.- Подпрограмма инициализации дисплея

LCD_Command — это макрос следующего вида:

Рисунок 4.- Исходный код макроса отправки коммады в LCD
Рисунок 4.- Исходный код макроса отправки коммады в LCD

Этот макрос сделан для удобства использования подпрограммы _LCD_Command. Дело в том, что параметры передаются в нее через регистры tmp1 и tmp2 и запись LCD_Command par1, par2 более естественна, чем три строчки из макроса. Стоит заметить, что и макрос и вызов подпрограммы с передачей параметров занимают одинаковое число тактов процессора и объем ROM.

Что же представляет собой подпрограмма _LCD_Command мы посмотрим на рисунке 5.

Рисунок 5.- код подпрограммы _LCD_Command

Как видно, это подпрограмма посылает управляющее слово (см рисунок 2) по I2C. Подпрограмма использует 3 регистра tmp0tmp1 и tmp2. В двух последних передаются параметры для подпрограммы ControlByte и DataByte.

Подпрограммы i2c_starti2c_stopi2c_send рассмотрены в этой статье.

В нашей реализации подпрограмма инициализации дисплея занимает 152 байта. Этот размер можно уменьшить, если обратить внимание на то, что ControlByte у всех команд, отправляемых в экран равен COMMAND. Как минимум, можно переписать макросы таким образом, чтобы лишний раз не обновлять регистр tmp1.

Очистка экрана (заливка определенным паттерном)

Что такое очистка экрана — это всего лишь заполнение видеопамяти символами определенного качества, в нашем случае это заполнение каждого сегмента страницы видеопамяти графического модуля нулями. Нижеприведенный код подпрограммы будет актуален только при использовании MEMORY_MODE = 0x00 или 0x01.

Рисунок 6.- исходный код подпрограммы очистки экрана
Рисунок 6.- исходный код подпрограммы очистки экрана

Мы передаем по I2C DATA байты в количестве 128x64 = 8192. Каждый переданный байт определяет тип очистки. Если передается 0 — экран очищается, если 0xFF— заливается цветом. Подпрограмма состоит из двух вложенных циклов по страницам памяти (8) и по количеству сегментов (128).

Для удобства использования подпрограмма также была завернута в макрос (рисунок 7)

Рисунок 7.- Макрос очистки экрана.
Рисунок 7.- Макрос очистки экрана.

Позиционирование

Рассмотрим теперь позиционирование на экране. Несмотря на то, что у нас дисплей 128x64 пикселя, адресовать номер страницы памяти и номер столбца. Каждая страница памяти это 8 строк. Поэтому, если мы хотим зажечь, допустим, 15 пиксель в 10 строке, мы должны выбрать 1 страницу памяти, в ней выбрать 15 сегмент и по этому адресу записать 4 (бинарное 0000 0100).

Выбор номера страницы памяти осуществляется командами B0-B7, или B0 | y.

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

Таким образом, позиционирование выльется в посылке 3 посылки по шине TWI (рисунок 8)

Рисунок 8.- Макрос позиционирования
Рисунок 8.- Макрос позиционирования

В этом макросе мы устанавливаем маркер текущего положения курсора в позицию (x,y), а также присваиваем соответствующие значения переменным LCD_X, LCD_Y.

Еще один неопределенный макрос SETMEM как раз и занимается сохранением данных в памяти.

Рисунок 9.- макрос сохранения числа в память SRAM
Рисунок 9.- макрос сохранения числа в память SRAM
Теги:
Хабы:
Всего голосов 11: ↑10 и ↓1+9
Комментарии18

Публикации