И снова привет, дорогой читатель! Продолжаю тему взаимодействия с экраном SSD1306. Сегодня я расскажу, как можно вывести на экран символы.
Отличие графического экрана от алфавитно-цифрового, скажем LCD1602, состоит в том, что у последнего есть встроенный генератор символов.
В случае же с SSD1306 - у него такого нет, поэтому придется его делать самостоятельно. Страница памяти нашего дисплея имеет размер 8 точек по вертикали, а 1 байт кодирует сегмент шириной 1 пиксель и высотой 8 пикселей, шрифт мы будем кодировать размером 5х8 (5 пикселей в ширину, 8 - в высоту) Таком образом, один символ представляется 5-ю байтами.
Нам не нужно кодировать всю таблицу ASCII, достаточно выбрать из нее непрерывный кусочек, в зависимости от того, какими символами мы будем пользоваться. В нашем примере мы возьмем символы с кодами от 0x20-0x5a. Этот интервал включает в себя латинские заглавные буквы, цифры 0-9, символы: пробел, !, ", *, $, %, &, ', (, ), *, +, запятая, -, точка, /, 0-9, :, ;, <, =, >, ?, @. Этих символов хватит вполне для организации вывода.
размер таблицы символов будет такой (0x5a-0x20+1)*5 = 295. на самом деле в сегменте кода такая таблица будет занимать не 295 а 296 байт - это особенность памяти в сегменте кода. Размер резервируемой памяти должен быть кратен 2. Чтобы избежать неявного резервирования еде одного байта, мы укажем его явно, добавив 0 к концу таблицы
Помимо этого, определим еще две константы: ASTART = $20 и FONT_W=5. Первая из них содержит код первого символа в таблице кодов, а вторая - говорит от ширине символа - 5 пикселей.
Алгоритм вывода символа на экран следующий - находим индекс символа в таблице символов, затем определяем адрес первого байта нужного символа, затем шлем FONT_W байт из таблицы символов в память SSD1306 и завершаем посылкой нулевого байта - символ пустого столбца.
На языке С эти выглядит так:
unsigned char idx = (ch-ASTART)*FONT_W;
i2c_transfer(TBL[idx], FONT_W)
здесь idx - номер первого байта, кодирующего наш символ ch.
На ассемблере это будет выглядеть так:
Здесь мы полагаем, что указатель на память в SSD1306 уже установлен в нужную строку и столбец.
В конечном итоге вызывающая программа может быть такой:
Аналогичным образом можно составить подпрограмму для вывода текста из SRAM и FLASH. Однако, в случае вывода из FLASH необходимо модифицировать подпрограмму _LCD_PutChar с рисунка 2, добавив сохранение в стеке текущих значений регистра Z (ZH, ZL) и их восстановление в конце подпрограммы.
И соответственно макросы:
Обратите внимание, что в случае печати из FLASH адрес нужно умножить на 2, так как адресация идет по словам.
Заключение
Ну вот, вроде бы все, если что было не понятно, задавайте вопросы).
PS
Что касается таблицы символов - если у вас вывод строго определенных фраз, то можно совсем сжать ее, оставив лишь нужные. В этом случае вам придется вместо обычных символов ASCII писать их номер согласно вашей новой таблице символов. Это муторно, но позволяет существенно сократить размер таблицы символов. Например, если у вас выводится лишь P= <число>, T=<число>, вместо нашей таблицы из 296 байт, можно составить таблицу из 15*5+1=76 байт (P, T, =, точка, пробел, 0-9), то есть выигрыш будет более чем в 3.8 раза!