Проект tinyAVR 16. Игра "Жизнь"

December 20, 2014 by admin Комментировать »

Эта математическая модель, изобретенная Джоном Конвеем — попытка смоделировать процессы реальной жизни при помощи простых правил. Игроки для нее не нужны, поэтому после настройки начального состояния не требуется никакого вмешательства. Подробности этой игры можно найти в Интернете и мы настоятельно рекомендуем вам почитать о ней. Предлагаемый проект позволяет пользователю смоделировать данную игру на дисплее Nokia при помощи микроконтроллера tinyAVR. В оригинальной игре используется двумерное поле бесконечного размера, но в нашем устройстве размер игрового пространства ограничен 16×16 ячеек. Пользователь может задать начальное состояние при помощи кнопок (как показано на рис. 4.21). После настройки начального состояния игру можно запустить и посмотреть на ее эволюцию.

Рис. 4.19. Печатная плата игрушки Тэнгу (сторона печатных проводников)

Рис. 4.21. Игра "Жизнь"

Спецификация проекта

Цель проекта — создать модель игры на микроконтроллере с графическим дисплеем и позволить пользователю устанавливать начальное состояние для запуска игры. Включение любого элемента игрового поля 16×16 осуществляется с помощью четырех кнопок. Схема питается от батареек.

Описание устройства

Рис. 4.22. Внешний вид игры

Схема устройства — та же самая, что и в проекте температурного регистратора. В том проекте использовалась только одна из имеющихся четырех кнопок, а теперь будут задействованы все кнопки. Назначение первых двух кнопок — перемещение курсора влево/вправо и вверх/вниз (они называются кнопками стрелок). Третья кнопка служит для переключения состояния элемента, а четвертая — для запуска игры. Изображение дисплея показано на рис. 4.22.

Программирование

Откомпилированный исходный код (вместе с файлом MAKEFILE) можно скачать по ссылке: www.avrgenius.com/tinyavrl.

Тактовая частота равна 8 МГц. Контроллер запрограммирован при помощи STK500 в режиме программирования ISP. Поясним наиболее важные фрагменты кода (листинг 4.6).

ЛСТИНГ 4д>

void place (void)

(

row=0; column=0; while(1)

{

if (! (PINA&ObO0000001))

{

_delay_ms(30);

while (! (PINA&ObOOOOOOOl));

_delay_ms ‘(30)

TIMSK1 = 0x00;

if (led[Of [row] & (l«column) )

{

pix_light (row, column, 1) ;

}

else if (!(led[0][roW]&(lcccolumn))) {

pix_light(row,column,0);

}

row++;

if (row== (ROWMAX+l) ) row = 0;

TIMSK1 = 0x01;

}

if (‘ (PINA&ObOOOOOOlO))

{

_delay_ms(30);

while (! (PINA&ObOOOOOOlO));

_delay_ms(3 0);

TIMSK1 = 0x00;

if (led[0] [row] & (l«column) )

{ pix_light (row, column, 1) ;

}

else if ( ! (led[0] [row] & (l«column) ) )

{

pix_light (row, column, 0) ;

}

column++;

if(column==(COLMAX+1)) column = 0;

TIMSK1 = 0x01;

}

if (! (PINA&ObO0100000))

{

_delay_ms (50);

while ( ! (PINA&ObOOlOOOOO) ), ;

_delay_ms (50);

TIMSK1 = 0x00; if(led[0] [row]& (lcccolumn)) led[0] [row] &=~ (l«column) ; else led[0] [row] |=l«column; if (led[0] [row] & (l«column) )

{

pix_light (row, column, 1) ;

}

else if ( ! (led[0] [row] & (l«column) ) )

{

pix_light (row, column, 0) ;

}

row++ ;

if (row== (ROWMAX+1) ) row = 0;

TIMSK1 = 0x01;

}

if (! (PINA&ObO0001000))

{

_delay„ms(3 0);

while (! (PINA&ObOOOOlOOO));

_delay_ms (3 0);

TIMSK1 = 0x00;

if (led[0] [row] & (l«column)

{

pix_light (row, column, 1) ;

}

else if (! (led[0] [row] & (l«column))) {

pix_light(row,column,0);

}

TIMSK1 = 0x01; break;

}

}

}

Функция, приведенная в листинге 4.6, служит для установки начального состояния (комбинации "живых” и "мертвых" ячеек). Каждая ячейка на дисплее LCD состоит из девяти пикселов. Верхние левые 2×2 пиксела у активных ячеек светятся, а остальные пять пикселов всегда выключены (во избежание слияния соседних пикселов). Все игровое поле состоит из 16×16 таких ячеек. Для оптимальной загрузки оперативной памяти мы использовали для представления этой конфигурации целочисленные массивы (размером по 16 элементов). Каадая переменная массива соответствует одной строке (ее 16 битов означают 16 столбцов). Настройка начального состояния осуществляется четырьмя кнопками: две перемещают курсор по строкам и столбцам, третья переключает состояние текущей ячейки, а последняя запускает игру.

while(1)

{

clearгam () ; stage=0;

for(unsigned char j=0;j<=5;j++)

{

cursorxy(48,j); writedata(OxFF); writedata(OxFF); writedata(OxFF);

}

TIMSK1 = 0x01;

//Вектор прерывания по переполнению place ();

TIMSK1 = 0x00;

//Отключение прерывания по переполнению cursorxy(52,0); put character(‘S’);

cursorxy(52,1); putcharacter(‘T’); cursorxy(52,2); putcharacter(Ά’); cursorxy(52,3); putcharacter( ‘ G’ ) ; cursorxy(52,4) ; putcharacter(‘E’); generation=0; generationl=l; while(1)

{

for (int row=0;row<=ROWMAX;row++)

{

for(int col=0;col<=COLMAX;col++)

{

if (led[generation] [row] & (l«col) ) led[generationl] [row] |=l«col; else led[generationl][row]

&=~ (l«col) ;

if(led[generation][row]&(l<<col)) //включено

{

check_neighbors(generation,row,col) if(alive>3||alive<2)

‘ {

led [generationl] [row] &= ~(l«col) pix_light(row,col,0);

}

}

else

if ( ! (led[generation] [row] & (l«col) ) )

{

check_neighbors(generation,row,col) if(alive == 3)

{

led [generationl] [row] |= l«col; pix_light(row,col,1);

}

}

}

}

generation = (generation==0)?1:0; generationl = (generation==0)?1:0;

//правила игры stage++; stagel=stage;

cursorxy(60,2);putcharacter (stagel/100+48)

stagel = stagel%100;

putcharacter(stagel/10+48);

stagel = stagel%10;

putcharacter(stagel+48);

_delay_ms(5 0 0); flag=0;

for(unsigned char i=0;i<=15;i++)

{

if (! (actual[i]==0))

{

flag=l;

break;

}

}

if ((flag==0) | | (stage==255))

{

clearram() ;

for(unsigned char i=0;l<=15;i++)

{

led[0][i)=0; led[l][i]=0; actual[i]=0; flag=0;

}

cursorxy(12,2); putstr("GAME OVER"); while(PINA&OxOl);

_delay_ms(30); while (! (PINA&OxOl));

_delay_ms(30); break;

}

}

}

Листинг 4.7 — это главный бесконечный цикл программы. Он выполняет два основных действия: проверяет состояние каждой ячейки (в соответствии с правилами игры) и обновляет дисплей. Одновременно он заполняет следующее состояние каждой ячейки (в соответствующей позиции массива led). Он проверяет количество ’’живых" соседей ячейки: больше трех или меньше двух (максимально соседей может быть восемь). Если одно из этих условий верно, то ячейка выключается ("умирает"). В том случае, когда у ячейки ровно три соседа — она сохраняется (или включается, если она "мертвая"). После проверки всех ячеек следующее состояние становится текущим (и т. д.). Для итерации между текущим и следующим поколениями требуются ТОЛЬКО две переменные (generation И generationl). Игра заканчивается, когда "умирают" (выключаются) все ячейки или когда значение stage (число "поколений") становится равно 255.

Остальные части кода инициализируют различные переменные, функции для сопряжения с LCD и процедуру обработки прерывания (для переполнения TIMER 1). Процедура обработки прерывания вступает в дело только при настройке начального состояния (для того, чтобы мигала текущая ячейка, на которую указывает курсор).

Работа устройства

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

Источник: Гадре, Д., Занимательные проекты на базе микроконтроллеров tinyAVR / Дхананья Гадре, Нигул Мэлхотра: Пер. с англ. — СПб.: БХВ-Петербург, 2012. — 352 с.: ил. — (Электроника)

Оставить комментарий

микросхемы мощности Устройство импульсов питания пример приемника провода витков генератора выходе напряжение напряжения нагрузки радоэлектроника работы сигнал сигнала сигналов управления сопротивление усилитель усилителя усиления устройства схема теория транзистора транзисторов частоты