Игровая консоль на stm32 и lcd nokia 5110

Игровая консоль на STM32 и LCD Nokia 5110

Введение

Наверняка у многих из нас в детстве были карманные игровые консоли. У тех, кто застал советское время, была игровая консоль «Электроника». Я не застал то время, поэтому у меня был «Тетрис» с черно-белым дисплеем, содержавший в себе несколько игр, такие как «танчики», «змейка», «тетрис» и т.д. Позднее стали появляться кнопочные мобильные телефоны Nokia с играми «Змейка», «Судоку» и т.п. Дисплеи от Nokia 5110 пользуются большой популярностью среди радиолюбителей, они более компактные и функциональные, нежели символьные на контроллере HD44780. Как только у меня оказался в руках LCD Nokia 5110, было решено создать на его основе игровую консоль. В качестве примера послужила игра «Пинг-понг».

Принцип работы дисплея

Дисплей построен на контроллере PCD8544 и имеет разрешение 84 х 48 пикселей. Команды и данные передаются в память дисплея с помощью интерфейса SPI. В зависимости от того, какой будет выставлен сигнал на входе D/C, приходящие байты по SPI будут восприниматься либо как данные, либо как команды. Так если будет логический 0, то все байты будут читаться как команды, в ином случае как данные. Сначала в режиме команд происходит инициализация дисплея, настраиваются температурный коэффициент, режим работы, контрастность, начальный адрес памяти дисплея. Все эти команды отлично описаны в даташите на контроллер PCD8544. После этого происходит переключение в режим данных, и память дисплея заполняется данными. О том, как заполняется дисплей приходящими данными, рассмотрим подробнее.

Вся рабочая область дисплея разделена на шесть строк. Каждая строка состоит из 84 столбцов размером 8х1 пикселей.

Командой отправляется начальный адрес памяти, затем по адресу записывается наш байт данных. Например, выставлен адрес х=0, у=0. Тогда первый пришедший байт данных запишется в нулевой столбец нулевой строки, то есть в самую верхнюю левую ячейку. С каждым новым байтом данных адрес памяти дисплея увеличивается на единицу, и байты записываются в следующие столбцы. Например, если пришел байт 11111111, то весь столбец 8х1 будет закрашен, а если 00000000, то ни один пиксель не будет закрашен. Сверху столбца идут младшие разряды байта, а снизу — старшие. Итак, первые пришедшие 84 байта заполнят всю нулевую строку, следующие 84 байта — первую строку, и так до заполнения всех строк. Описанная выше адресация называется вертикальной.

Выбор микроконтроллера и схема устройства

«Сердцем» игровой консоли стала отладочная плата на микроконтроллере STM32F103C8T6. У микроконтроллера имеется 64 Кб программной памяти, что может спокойно хватить на 3-4 игры в одном устройстве. Питание устройства происходит от «Кроны» через стабилизатор напряжения на 5 В. Пять вольт подается на отладочную плату, а на самой плате имеется еще стабилизатор на 3.3 вольта, от которого и питается микроконтроллер. Напряжение 3.3 вольта с отладочной платы подается для питания на сам дисплей, что позволяет не беспокоиться о согласовании логических уровней МК и дисплея. Для озвучки консоли к пину А7 подключен пьезоэлектрический динамик.

Для разработки ПО использовалась среда «CooCox CoIDE». Весь проект состоит из следующих библиотек и заголовочных файлов:

— f10x-pcd8544.c и f10x-pcd8544.h — библиотека для работы с дисплеем;

— font6x8.h — здесь хранятся английские, русские символы и графические объекты для игры;

— Game_board.c и Game_board.h — здесь у нас код игры «Пинг-Понг» на одного и двух игроков;

— Sound.h — тут хранятся массивы с мелодиями для игры.

Сейчас мы рассмотрим работу с этими библиотеками поподробнее.

Библиотека для работы с графикой

К данной библиотеке была добавлена одна очень необходимая для созданий игр функция void lcd8544_putobject(unsigned char px,unsigned char py,unsigned char width,unsigned char height,unsigned char object[]). Функция позволяет выводить на дисплей изображения любых размеров (естественно не больше 84х48) по заданным координатам. Таким образом в файле font6x8.h мы можем создать массив изображения любого графического объекта и выводить его уже на дисплей. Например, можно нарисовать танк, человечка, всё что угодно. Аргумент px — координата по х, py — по y, следующие два аргумента это ширина и высота изображения, последний аргумент функции — строка с названием массива изображения. Создав такой графический объект, мы можем манипулировать с его координатами, как нам необходимо: заставлять двигаться по экрану, взаимодействовать с другими графическими объектами.

Создать графический объект в font6x8.h можно вручную, например, такой:

Так мы создали квадрат 8х8. У нас в массиве 8 элементов, каждый элемент представляет из себя байт 11111111. Как мы помним, в дисплее у нас происходит вертикальная адресация, значит эти восемь байт из массива и создадут изображения квадрата.

Для создания массивов удобно пользоваться программой «LCD Vision». Запускаем программу, выбираем File — New Font, задаем, например, размер 8х8.

Это режим создания символов любых размеров, этим режимом удобно пользоваться, когда рисуем по пикселям. Нарисуем что-либо в символе «пробел», код этого символа 0х20.

Выбираем File — Export, а после File — Save Export. Файл сохраняем в формате .с . Открываем созданный файл с помощью блокнота, в нем содержатся массивы на все нарисованные символы. Поскольку нарисован только символ «пробел», то и будет массив только с этим символом, а в остальных массивах одни нули.

Массивы для вертикальной адресации находятся в середине файла. Копируем полученный массив в font6x8.h , и дело почти готово. Осталось только зайти в f10x-pcd8844.c и в теле функции lcd8544_putobject дописать строку рядом с подобными строчками:

После этого уже будет возможно использовать наш новый графический объект. Пример использования нового массива:

Создание игры «Пинг-Понг»

Используя функцию lcd8544_putobject можно создавать уже любые игры, остается только создать необходимые графические объекты и задать им перемещение по определенному алгоритму. Так была создана игра «Пинг-Понг». Сейчас подробнее о функционале игры.

При запуске игры появляется главное меню с выбором режимов на одного и двух игроков, при этом играет фоновая мелодия. Выбор пунктов меню осуществляется кнопками Right Platform1, Left Platform1, Button Select. Также находясь в главном меню, мы можем отключить или выключить музыку и звуки в игре, нажав Button_Cancel. Выбрав пункт «1 ИГРОК» , мы окажемся в меню выбора сложности. В зависимости от уровня сложности, будет различной начальная скорость мяча. После выбора уровня сложности начинается игра против бота, до семи забитых голов. После гола нажмите Button Select, игра продолжится дальше. Игру можно ставить на паузу, нажимая Button Select, а также нажатием Button Cancel выходить из нее. При выборе пункта «2 ИГРОКА» возможно играть уже с другом, вторая платформа уже управляется кнопками Right Platform2 и Left Platform2.

Код игры обоих режимов игры написан в Game_board.c в функциях Single_Player() и Two_Player(). Функция Game_Init() выводит на дисплей счет и разметочную линию. Подробнее об алгоритме игры можете почитать в комментариях в исходном коде. В файле main.с реализовано двухуровневое меню, а также функции воспроизведения мелодии и звука. Сама мелодия хранится в виде массива в Sound.h.

Устройство собрано в распределительной коробке для электромонтажа, форма коробки круглая и довольно удобная.

Прошивка загружается в микроконтроллер с помощью программатора ST-Link V2. Для прошивки можно использовать саму среду разработки «CooCox» либо отдельную небольшую утилиту «STM32 ST-LINK Utility». Файл прошивки имеет формат .bin.

К статье прилагаются видео с демонстрацией работы устройства и проект с исходным кодом.

Игровая консоль на stm32 и lcd nokia 5110

писал на Cи в среде Coocox

В архиве два варианта библиотеки:
1. soft-SPI
2. hard-SPI

второй вариант, использующий аппаратный SPI, можно попробовать настроить на работу через DMA

работа библиотеки проверена на STM32 VL Discovery

представь что у тебя строки идут по байтно сверху вниз (2 байта) в порядке бит (в принципе если ты знаешь как символ рисуется на ЖКИ то это как раз один столбец ЖКИ экрана.. ну даже не один столбец а первые 16 строк первого столбца 🙂
7 +
6 |
5 |
4 |
3 +— это как раз первый байт, пиксельные строки с 0 по 7
2 |
1 |
0 +
7 +
6 |
5 |
4 |
3 +— это второй байт, пиксельные строки с 8 по 15
2 |
1 |
0 +

Читайте также  Сечение кабеля для проводки

это понятно? обычно ты определяешь адрес первого байта и выводишь в него символ по байтно (если символ имеет не более 8 пикселов в высоту) — надеюсь как найти столбец для вывода ты понимаешь..

а теперь посмотри что нужно сделать если нужно выводить попиксельно (первый столбец это бит байта, второй столбец это бит символа для вывода)
7 +
6 |
5 |
4 7 | +
3 6 +—— это первые восемь строк экрана
2 5 | |
1 4 | |
0 3 + +—— а это наш символ с третьей строки
7 2 |
6 1 |
5 0 +
4
3
2
1

получается что верхний (7) бит первого байта экрана — это нулевой пиксель по вертикали, шестой бит — первый пиксель и так далее,
следовательно символ мы выводим с 3ей пиксельной строки
соответственно байт для вывода символа нужно сдвинуть вправо на 3 позиции (чтобы 7ой бит символа оказался в 4ом бите строки) — этот полученный байт накатываем на строку текущую..
а в следующей строке мы наоборот наш символ сдвинем влево на те же 5 (8-3) позиций чтобы второй бит оказался на месте 7го бита второго байта экрана
вот в принципе и весь алгоритм вывода..

плюсы его в том что символ рисуется как бы побайтно а не попиксельно как делает большинство — прирост в скорости огромный.. да и код вроде не такой уж и сложный получился

теперь к твоем случаю:
получается что тебе сдвигать придется не 1 а 2 байта (16 точек по вертикали !)
ниже я вывожу символ со второй пиксельной строки экрана
7
6
5 7
4 6
3 5
2 4
1 3
0 2
7 1
6 0
5 7
4 6
3 5
2 4
1 3
0 2
7 1
6 0
5
4
3
2
1

несмотря на кажущуюся сложность — порядок тот же !! просто как бы рисуем два символа одновременно !!
просто один в координатах x, y, а другой в координатах x, y+8
у тебя одна задача: сделать свой знакогенератор, и написать код который будет доставать части символа для первого вывода (в координатах x,y) и второй части для координат x, y+8

сдвиг на 3 позиции вправо — это и есть деление на 8
это нужно для того чтобы из пиксельной позиции по вертикали вычислить байтовую строку
например тебе нужно вывести строки в координате по вертикали с 33 строки
в двоичном виде это 10 0001
теперь двигаем это значение на 3 позиции вправо: получаем 100 или 4 в десятичном виде..
то есть ты должен выводить символ в 4ой байтовой строке по вертикали (это как раз 32ая пиксельная строка)

теперь нужно посчитать с какого пиксела нужно начать вывод в нашей 4ой байтовой строке
для этого мы из 7 (число бит в байте — 1) вычитаем 001 (это как раз то что сдвинули за пределы байта). и получаем 6 — это как раз бит с которого нужно сделать вывод .
вот тебе и две операции:

КоординатаYCимвольная=YПиксельнаяДляВывода >> 3
КоординатаYPixельная=7-(YПиксельнаяДляВывода & 0x07)

я в коде эксперементировал, и не уточнял команда СИ >> циклически сдвигает или нет, поэтому перед сдвигом на всякий случай обнулял 3 младших бита и получил конструкцию:
КоординатаYCимвольная = (YПиксельнаяДляВывода & 0xF8) >> 3

Игровая консоль stm32

Немного шутеров для stm32; как, зачем, что получилось.

Предисловие

Будучи поклонником «старой» школы шутеров с одной стороны и embedded-разработчиком с другой, я всегда испытывал интерес, как и почему авторам той эпохи удавалось воплощать новый жанр, требующий совершенно новых подходов на весьма «скромном» железе. И я решил попробовать запустить нечто подобное используя решения на основе современных МК — тут и bare-metal и «скромные» ресурсы и довольно мощный инструмент отладки (stm32, имхо). И так, мой выбор пал на плату разработчика stm32f769i discovery.

Примечания

На текущий момент сборка возможна только из среды Keil MDK (загрузчик, игры) или же с помощью arm-gcc + make (только загрузчик). На данный момент доступны порты для — Quake I (+mods), Doom (+mods), Duke Nukem (+mods), Hexen, Heretic. С учетом всех модификаций, список может быть значительно расширен.

Начнем

Архитектура

Так как конечная реализация требует возможности независимого запуска различных игр без обновления прошивки МК, возникла необходимость в некотором варианте «загрузчика», итак:

  1. Загрузчик; работа с памятью — «установка» приложения (игры), запуск.
  2. Драйвер; Обслуживание HAL уровня системы и сопутствующие функции, предача API в приложение.
  3. Приложение; Конечная программа, не возвращает управление в загрузчик.

1. Загрузчик

В основе лежит модель IAP (In-Application-Programming) — драйвера на примере от ST-microelectronics.

Особенность этого подхода в том, что нет необходимости менять когфигурацию загрузки МК,
Все «тело» загрузчика находится в основной памяти, и это в свою очередь позволяет использовать stm32f769i discovery «из коробки».

Основной функционал этого уровня — чтение .bin файла, запись его содержимого в память МК и передача управления. На этом этапе ключевой момент — прочитать адрес точки входа и адрес указателя стека, второе не требуется — т.к. приложение не возвращает управления —
стэк является общим и в перезаписи указателя нет необходимости. Вызов так же может быть выполнен через указатель на функцию. Таким образом, в результате будет получен «гибридный» загрузчик — его «драйверная» часть продолжает обслуживать приложение, в то время как ресурсы самого загрузчика выгружены.

2. Драйвер

Драйвер выполнен в виде «обертки» над уровнем HAL, предоставляя доступ к необходимым ресурсам — файловая система, дисплеймонитор, звук, игровой контроллерсенсор дисплея. Для дальнейшего использования, API драйвера передается в виде структуры указателей через «общую память» — участок памяти зарезервированный как для загрузчика так и для ответной стороны. Подобная манипуляция требует затрат памяти, и возможно лучшим решением было бы использовать SWI (soft-interrupt, svc call), но для этого в свою очередь необходимо иметь возможноть смены контекста — т.к. не все вызовы могут быть обработанны в прерывании. Так же «общая» память используется для передачи пользовательских аргументов (например через консоль), обязательное условие — добавить атрибут no-init для этого участка, это позволит избежать его перезаписи runtime-с библиотекой на момент инициализации пользовательского приложения.

3. Приложение

Как следствие — единственное что необходимо знать на момент сборки приложения — это архитектуру ядра процессора, никаких зависимостей из HAL нет, так же отсутствует таблица векторов прерываний, — все прерывания обрабатываются загрузчиком. Приложение в результате использует гораздо меньше места в памяти программ — благодаря тому что часть функционала «зашита» вместе с загрузчикомдрайвером, что позволяет установить его в область SRAM data (встроенной оперативной памяти). Это в свою очередь позволяет значительно сократить количество циклов записи Flash памяти и так же ускорить процесс отладки и выполнения в целом. Из минусов же — на момент отладки, вызов приложения возможно произвести только извне, например командой из консоли (COM порт сверх ST-Link, VCOM), для этого используется очень упрощенный вариант командной строки.

Особенности разработки

Память

5.5mbytes). Разместить такой объем возможно лишь в sdram, но т.к. эта же память используется загрузчиком для хранения временных данных — изображения, звук, содержимое файлов и т.д. необходимых только до запуска приложения, — было решено разделить управление этой частью памяти — с каждой стороны есть свой malloc/free. После запуска — драйвер использует указатели на функции mallocfree, которые при необходимости, передаются как параметр в функцию вызова. То есть, после запуска игры — драйвер не может напрямую выполнить аллокацию из sdram. Интересный факт о D-Cache и I-Cache — в силу особенностей обращения с внешней памятью — перед запуском необходимо выключать обе линии, т.к. sdram повторно инициализируется, все бы хорошо, но есть одно «но» — необходимо всегда инвалидировать кэш, иначе, по умолчанию он сохраняет валидное состояние всех линий, в то время как они были перезаписанны в промежутке когда кэш был выключен.
Еще одна особенность — все данные загрузчика помещаются в DTCM секцию, это позволяет не задействовать кэш при обращении к памяти (то же самое позволяет выполнить MPU) и как следствие — решаются проблемы когерентности при работе с DMA;
В связке — CPU -> D-Cache -> Memory

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

Записки дилетанта

Так вийшло що я цікавлюся безліччю речей, але так ні в чому не став професіоналом. Однак впорядкувати думки та поділитися ними з друзями та знайомими іноді хочеться.

понеділок, 9 січня 2017 р.

Дисплей Nokia 5110 на контролері PCD8544 — бібліотека для STM32

Увага! Так як бібліотека мала б розвиватися, дана стаття може доволі швидко застаріти. Але гарантій не дам. 🙂

Огляд

  • Дозволяє під’єднувати довільну кількість дисплеїв (1).
  • Підтримує вивід тексту: окремих літер, С-стрічок, чисел, та стрічок, форматованих у стилі printf() (2).
  • Підтримує вивід довільних прямих. (5)
  • Вміє виводити прямокутники, зокрема — заповнені. (5)
  • Вивід може відбуватися як «білими», так і чорними пікселями.
  • Надає доступ до всіх режимів дисплею та безпосереднього керування його параметрами.
  • На кожному дисплеї може використовуватися декілька незалежних вікон. Із кожним вікном пов’язаний свій «графічний» курсор, який задає лівий верхній кут виводу наступної літери (3).
  • Для кожного дисплея підтримує свій «відео»-буфер, котрий при оновленнях передається на пристрій для відображення.
  • Шрифт вкомільовується в код, моноширинний, але розмір символу не фіксується бібліотекою (4).
  • У шрифті по замовчуванню підтримується кирилиця — українська та російська. Кодування — ASCII + CP1251.
  • На жаль, автоматично генерованої документації в коді ще немає. Планується. Поки дивіться код та користуйтеся цим постом.

Для більшої гнучкості код складається із трьох частин, кожна із яких представлена парою файлів, .h i .c, плюс файл із шрифтом:

  1. lcd5110_ll.h/lcd5110_ll.c — низькорівневий код (ll — low-level), який безпосередньо взаємодіє із дисплеєм, вміє його ініціалізувати, передати низькорівневі команди та дані.
  2. lcd5110_hal.h/lcd5110_hal.c — власне, Hardware Abstraction Level. «Абстрагує» організацію RAM дисплея. Реалізовує функції виведення пікселів та растрових зображень (bitmap). Маніпулює лише буфером — з апаратурою безпосередньо не взаємодіє. (Тому назва може не дуже вдала, але Buffer Abstraction Level звучатиме ще гірше :-).
  3. lcd5110.h/lcd5110.c — високорівневий код. Виведення тексту, ліній, прямокутників, реалізація вікон та курсорів — тут.
  4. font6x8.h — шрифт по замовчуванню.

Імена функцій, правда, потребують певного впорядкування.

В проект слід додати всі сім файлів, але користувачу достатньо включати «lcd5110.h».

Технічні подробиці:

  • Конфігурування дисплею — динамічне, в стилі HAL. Тобто, створюється структура, котра містить вказівник на дескриптор апаратного SPI, номери пінів та портів RST, CE, DC і передається всім функціям.
  • Такий підхід повільніший і генерує трохи більший код, ніж визначення пінів, портів, SPI за допомогою #define, але багато гнучкіший. Планую, хоч і без гарантій, в майбутньому написати її реалізацію (можливо, неповну — лише для тестів) із використанням статичного підходу (#define) та на С++, із використанням шаблонів — щоб порівняти як зручність різних підходів, так і їх ефективність (з точки зору розміру коду та його швидкодії).
  • (1) Обмеження поточної реалізації: на даний момент використовує апаратний SPI, тому кількість одночасно керованих дисплеїв обмежується кількістю апаратних SPI. Одночасно підключених дисплеїв може бути значно більше — завдяки CE, кілька пристроїв можуть знаходитися на одній шині. Планую додати механізм вибору реалізації послідовного інтерфейсу.
  • Поточна реалізація використовує STM32 HAL. Попередньо виглядає, що спричинені ним накладні витрати тут не є серйозним обмеженням, але в майбутньому планую дослідити це питання ретельніше.
  • Обмеження поточної реалізації: поки пам’ять дисплею оновлюється повністю. Планується можливість часткових оновлень.
  • Обмеження поточної реалізації: ніяких спроб оптимізувати вивід бітмапів поки не зроблено, хоча інфраструктура для того є.
  • Обмеження поточної реалізації: DMA поки не використовується. Для передачі «відео»-даних у ньому може бути сенс.
  • (2) Якщо користуватиметеся виводом floating-point чисел, не забудьте його підключити (розділ «Додаток: SemiHosting i libc для лінивих», після слів «По замовчуванню, SW4STM32 використовує Newlib-nano без підтримки floating-point чисел при вводі-виводі«).
  • (3) Обмеження поточної реалізації: Якийсь Z-порядок вікон поки не передбачений. Котре вікно останнім перемалювалося, те і зверху. При чому, вікна прозорі. Літери, правда, ні. Планується можливість керувати і тим і тим.
  • (4) Вивід літер іде підряд, тому шрифт повинен передбачати порожню вертикальну лінію, щоб символи не зливалися.
  • Недолік поточної реалізації: CE постійно активний — дисплей споживає зайве, та й вразливіший до завад на пінах.
  • Взагалі, поки бібліотека надміру конкретна. Потім узагальнюватиму для інших споріднених дисплеїв.
  • Недолік поточної реалізації: майже гарантовано — доволі багато багів. Всі знайдені виправив, але місця для них — багато.
  • (5) Обмеження поточної реалізації: лінії та прямокутники поки товщиною лише 1 піксель. Звичайно, можна емулювати товстіші, малюючи декілька ліній поруч.
  • Обмеження поточної реалізації: не реалізовано прокрутку (scrolling).

Подключение дисплея Nokia 5110 к Arduino

В данной статье мы научимся работать с графическими LCD дисплеями на примере экрана Nokia 5110. Это довольно популярный дисплей, выделяющийся низкой стоимостью и возможностью выводить в удобном виде не только текстовые, но и графические данные (графики, изображения и т.д.). Разрешение экрана Nokia 5110 – 48×84 точки. Мы узнаем, как подключать дисплей Нокиа к Ардуино и приведем пример скетча для работы с ним.

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

Для начала давайте рассмотрим подключение данного дисплея к Arduino и разберемся с интерфейсом передачи данных. На плате дисплея имеются 8 выводов:

  • RST — Reset (сброс);
  • CE — Chip Select (выбор устройства);
  • DC — Data/Command select (выбор режима);
  • DIn — Data In (данные);
  • Clk — Clock (тактирующий сигнал);
  • Vcc — питание 3.3В;
  • BL — Backlight (подсветка) 3.3В;
  • GND — земля.

Соединение

Как вы уже могли заметить, питание дисплея (Vcc) должно осуществляться напряжением не выше 3.3В, то же напряжение является максимальным и для подсветки дисплея (BL). Тем не менее, логические выводы толерантны к 5В логике, используемой Arduino. Но все же рекомендуется подключать логические выводы через резисторы 10 кОм, тем самым вы сможете продлить срок службы дисплея.

Также стоит отметить, что существуют версии дисплеев (как правило с красной платой) с выводом LIGHT вместо BL. В таком случае включение подсветки осуществляется подключением данного вывода к минусу питания (GND).

Пин RST (активный LOW) отвечает за перезагрузку дисплея, а с помощью пина CE (активный LOW) контроллеру дисплея сообщается что обмен данными происходит именно с ним. Вход DC отвечает за режим ввода – ввод данных, либо ввод команд (LOW – данные, HIGH – команды). Вход Clk позволяет контроллеру дисплея определять скорость передачи данных, а через пин DIn происходит непосредственно передача данных в контроллер дисплея.

Скетч и библиотека для работы с дисплеем

Для работы с данным дисплеем существует множество библиотек, мы же будем использовать весьма простую и функциональную библиотеку , доступную по адресу http://www.rinkydinkelectronics.com/library.php?id=44. Данная библиотека позволяет работать с дисплеем с помощью 14 простых функций:

Функция Назначение
LCD5110(SCK, MOSI, DC, RST, CS) Объявление дисплея с указанием пинов подключения.
InitLCD([contrast]) Инициализация дисплея с опциональным указанием контрастности (0-127), по умолчанию используется значение 70.
setContrast(contrast) Изменение контрастности (0-127).
enableSleep() Переводит экран в спящий режим.
disableSleep() Выводит экран из спящего режима.
clrScr() Очищает экран.
clrRow(row, [start], [end]) Очищает выбраную строку (номер row), от позиции start до end (опционально).
invert(true), invert(false) Включает и выключает инверсию содержимого LCD экрана.
print(string, x, y) Выводит строку символов (string) с заданными координатами (x, y); вместо x-координаты можно использовать LEFT, CENTER и RIGHT; высота стандартного шрифта 8 точек, поэтому строки должны идти с интервалами через 8.
printNumI(num, x, y, [length], [filler]) Выводит целое число (num) на экран на заданной позиции (x, y); опционально: length – количество символов, резервируемых для числа; filler – символ для заполнения «пустот», если число меньше желаемой длины length (по умолчанию это пробел ” “).
printNumF(num, dec, x, y, [divider], [length], [filler]) Выводит число (num) с плавающей запятой; dec – число знаков после запятой; опционально: divider – знак десятичного разделителя, по умолчанию точка “.”, length и filler – по аналогии с предыдущей функцией.
setFont(name) Выбирает шрифт; встроенные шрифты – SmallFont, MediumNumbers и BigNumbers.
invertText(true), invertText(false) Инвертирует текст, выведенный с помощью функций print, printNumI и printNumF (вкл./выкл.).
drawBitmap(x, y, data, sx, sy) Выводит картинку на экран по необходимым координатам (x, y); data – массив, содержащий картинку; sx и sy – ширина и высота рисунка.
Читайте также  Срок эксплуатации проводки в квартире

Рассмотрим работу с дисплеем с помощью данной библиотеки на примере простого скетча:

После того как мы рассмотрели базовые функции библиотеки, остановимся более подробно на функции drawBitmap и рассмотрим особенности вывода изображений на экран.

Для начала нам понадобится интересующее изображение в формате .bmp.

Далее необходимо скачать программу Image Generate от Alex_EXE по адресу https://alex-exe.ru/programm/image-generate/. В окне программы устанавливаем необходимое разрешение нашего изображения на дисплее (должно быть меньше, чем 84 пикселя по горизонтали и 48 по вертикали), нажимаем «установить новый размер».

Нажимаем «установить новый размер»

После этого нажимаем «Картинка», «Открыть», выбираем наш файл, жмем «преобразовать».

Жмем «преобразовать»

Нажимаем «Применить»

Теперь жмем на кнопку «Массив» и копируем появившийся массив в новый скетч.

Теперь жмем на кнопку «Массив» и копируем появившийся массив в новый скетч

Выводы

Таким образом, мы подробно рассмотрели базовые возможности работы с дисплеем Nokia 5110 с помощью библиотеки LCD5110_Basic, научились быстро и просто выводить собственные изображения на экран и разобрали нюансы, связанные с подключением дисплея к платформе Arduino.

NOKIA 5110 подключение

Сегодня я расскажу как подключать дисплей от некогда очень известного телефона НОКИА – 5110.
Мы научимся выводить текст и рисовать различную графику.
Вот примеры того, что будет в этом уроке.
Для подключения к Ардуино была написана библиотека, а для отображения кириллицы создан русификатор.
Он переводит UTF-8 в Windows-1251. Вот его мы и сможем увидеть на экране.
Нам потребуется две библиотеки от компании Adafruit

  1. Adafruit_GFX
  2. Вторая, Adafruit_PCD8544

Скачать можно с гитхаба или по ссылке в описании к видео.
Nokia-5110 – это Монохромный дисплей. Разрешение этого дисплея 84×48 точек.

Для подключения у него 8 посадочных мест, как сверху, так и снизу. Это сделано для удобства расположения дисплея в устройствах.


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


Важно не забыть, что питание дисплея 3,3 вольта. НЕ 5 ВОЛЬТ.
Тоже относится и для питания подсветки дисплея.

Подключение оставшихся выводов так же рассчитано на питание 3,3 вольта.
Я уже давно использую такие дисплеи и у меня на канале есть несколько видео где показаны разные устройства с выводом информации на Nokia-5110.
Подключаю напрямую к выводам Ардуино, БЕЗ РЕЗИСТОРОВ, и всё работает уже долгое время. Как будете делать вы я не знаю.
Можете подключать через дополнительные резисторы, или использовать преобразователи, которые получая на вход 5 вольт преобразуют его в 3,3 вольта.

Есть различные варианты дисплеев. Например, отличаются по цветам платы. Если у вас красная плата, и вывод обозначается как LIGHT — то он подключается к + 3,3 вольта.
Если синяя, и вывод обозначается как BL — то он подключается к земле.
Но лучше уточнить у продавца. Всегда могут быть исключения.

Так же я всегда устанавливаю подстроечный резистор на 10 кОм, чтобы регулировать яркость дисплея вручную. Вывод подсветки подключается к центральному контакту резистора, а два крайних – это +3,3 и GND.

Теперь давайте попробуем загрузить скетч из примера библиотеки и посмотрим, как он работает. Это довольно сложный пример для того, чтобы обучаться.
Я в своих примерах показываю, как сделать проще.

Рассмотрим первый скетч.
Скачать его можно по ссылке в описании к видео.
Я прокомментировал каждую строчку кода на нашем ВЕЛИКОМ и МОГУЧЕМ, что бы было понятно что и для чего.

Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);

void setup() <
display.begin();
display.setContrast(50); // установка контраста
display.clearDisplay();
>

void loop() <
display.setTextSize(1); // размер шрифта 1
display.setTextColor(BLACK); // цвет текста темный
display.println(«Hello, world!»); // отображаем надпись
display.setTextSize(2); // увеличиваем шрифт на 1
display.println(random(1,10000)); // выводим число от 1 до 10000
display.setTextSize(3);
display.print(random(1,10000));
display.display();
delay(1000); // задержка в секунду
display.clearDisplay(); // очищаем дисплей
>

Теперь попробуем вывести русский текст.
Загружаем скетч-2

Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);

void setup() <
display.begin();
display.cp437(true);
display.setContrast(50); // установка контраста
display.clearDisplay();
>

void loop() <
display.clearDisplay();
// Рисуем квадрат
display.drawRect(0, 0, 84, 48, BLACK); // отступ — Слева Сверху Ширина Высота

display.setTextSize(2); // размер шрифта 2
display.setTextColor(BLACK); // цвет текста чёрный
display.setCursor(8,5); // Устанавливаем курсор в то место откуда будем писать Лево-Верх
display.println(utf8rus(«Привет»));
display.setTextSize(2); // размер шрифта 2
display.setTextColor(BLACK); // цвет текста чёрный
display.setCursor(8,25);
display.println(utf8rus(«народ!»));

display.display();
delay(1000); // задержка в секунду
display.clearDisplay(); // очищаем дисплей
>

/* Функция перевода UTF-8 to Windows-1251 */
String utf8rus(String source)
<
int i,k;
String target;
unsigned char n;
char m[2] = < '0', '' >;

k = source.length(); i = 0;

if (n >= 0xC0) <
switch (n) <
case 0xD0: <
n = source[i]; i++;
if (n == 0x81) < n = 0xA8; break; >
if (n >= 0x90 && n = 0x80 && n

Теперь попробуем вывести русский текст.

И-и-и-и-и, ничего у нас не получилось.
Вместо русских букв получаются кракозябры.

Но не переживайте. Сейчас исправим.
Скопируем файл glcdfont.c в папку с библиотеками Ардуино.

Обычно это находится по адресу
Admin — Documents — Arduino – libraries — Adafruit-GFX-Library
копируем туда файл glcdfont.c с заменой

В setup добавляем строчку

void setup() <
display.begin();
display.cp437(true);

И в самый конец, после функции loop() копируем функцию перевода UTF-8 в Windows-1251

/* Функция перевода UTF-8 to Windows-1251 */
String utf8rus(String source)

И,… вуаля, теперь можно работать с русским шрифтом.

Нарисуем окружность.
Заполним весь экран кругами.
Раньше мы всегда писали чётными чернилами, а что если белыми?
Посмотрим?

Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);

void setup() <
// инициализация и очистка дисплея
display.begin();
display.clearDisplay();
display.display();

display.setContrast(50); // установка контраста
delay(1000);
>

// окружность в центре
display.clearDisplay();
display.drawCircle(display.width()/2, display.height()/2, 20, BLACK);
display.display();
delay(5000);
display.clearDisplay();

for (int16_t i=0; i

for (int16_t i=0; i

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

Дисплей Nokia 5110 имеет разрешение 84×48 точек. Поэтому и картинки должны быть не больше этого размера. В принципе здесь нет ничего нового.
Как делать массивы из картинок .bmp, я подробно рассказывал в видео про матрицу 16*16. Если не смотрели, то обязательно посмотрите.
Здесь нас интересует только 2 строчки.

static const unsigned char PROGMEM leoBmp[]

Где мы пишем название нашего массива

2. где мы его вызываем.
Цифры – это размер картинки.

display.drawBitmap(0, 0, leoBmp, 84, 48, BLACK);

А теперь выведем какой-нибудь логотип.
Например, льва.

Смотрите в видео.

Не забываем подписываться на канал, если вам интересно что я делаю.
Ставим лайк и оставляем комментарии – этим вы покажете мне, что я не просто так делаю обучающие уроки.
До встречи.