Игровая консоль на 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 — здесь у нас код игры «Пинг-Понг» на одного и 2-х игроков;

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

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

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

Библиотека была взята отсюда — http://vg.ucoz.ru/forum/9-100-1 . Данная библиотека позволяет выводить текст на латинице и кириллице, строить прямые, прямоугольники, выводить строки и целочисленные переменные типа int. В файле f10x-pcd8555.h в директивах #define можно настроить порт и пины микроконтроллера, к которым подключается дисплей. Как пользоваться функциями, довольно понятно, достаточно посмотреть на прототипы функций в f10x-pcd8544.h.  Единственное, что может быть непонятным сразу, это аргумент mode во многих функциях, если мы задаем 0, то выводится черный текст на белом фоне, если 1 задать, то соответственно наоборот. Приведу небольшой пример работы с функциями:

int main(void)
{
lcd8544_init(); // инициализация дисплея
lcd8544_putstr(0,0,»ПРИВЕТ»,0);
lcd8544_putstr(0,10,»КАК ДЕЛА?»,0);
lcd8544_refresh(); // вывод массива на дисплей
 while(1)
 {
 }
}

К данной библиотеке была добавлена одна очень необходимая для созданий игр функция 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 можно вручную, например, такой:

const unsigned char NashMassiv[]= { // 8×8
0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF,
};

Так мы создали квадрат 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 дописать строку рядом с подобными строчками:

if((strcmp(object,»NashMassiv»))==0) fontpointer=NashMassiv;

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

int main (void)
{
lcd8544_init();
lcd8544_putobject(10,10,8,8,»NashMassiv»);
lcd8544_refresh();
while(1)
{
}
}

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

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

При запуске игры появляется главное меню с выбором режимов на одного и 2-х игроков, при этом играет фоновая мелодия. Выбор пунктов меню осуществляется кнопками 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.с реализовано 2-хуровневое меню, а также функции воспроизведения мелодии и звука. Сама мелодия хранится в виде массива в Sound.h.

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

 

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

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


Список радиоэлементовОбозначение
Тип
Номинал
Количество
ПримечаниеМагазинМой блокнот

МК STM32STM32F103C81

LCD-дисплейNokia 51101
VR
Линейный регуляторL78L051
EP1
Пьезоэлектрический динамик1

Кнопка без фиксации6
C1,2
Конденсатор0,1 мкФ2
R1
Резистор300 Ом1
Добавить все

Скачать список элементов (PDF)

Прикрепленные файлы:

Добавить комментарий

Ваш адрес email не будет опубликован.