04 GRA


Wydział Informatyki

Katedra Systemów Czasu Rzeczywistego

Laboratorium Architektury Komputerów

Data: poniedziałek 17:00

27.10.2008

Sprawozdanie z projektu nr. 4-5

Skład grupy:

Łukasz Jacewicz

Michał Jurczuk

Prowadzący:

dr inż. Mirosław Omieljanowicz

Ocena:

Cel projektu:

Gra, w której poruszamy się samochodem (x'em) i omijamy przeszkody (zera), jeżeli ominiemy odpowiednią ilość przeszkód wygrywamy. Tempo gry systematycznie wzrasta, zmniejszając czas reakcji gracza w którym może nacisnąć przycisk. Po zakończeniu gry wyświetlana jest liczba zdobytych punktów.

Wiadomości teoretyczne:

Informacje wstępne o wyświetlaczu LCD.

EasyWeb2 nie zawiera wbudowanego sterownika wyświetlacza, dlatego też do wyświetlania wykorzystuje specjalizowany układ wyświetlacza LCD z własnym sterownikiem. Rolę tego sterownika pełni układ firmy Hitach HD44780. Komunikacja z układem polega jedynie na przesyłaniu danych, które mają być wyświetlone, oraz instrukcji określających w jaki sposób te dane mają być wyświetlane.

Wymiana danych pomiędzy układem HD 44780, a mikrokontrolerem może odbywać się za pośrednictwem ośmio lub czterobitowej magistrali danych. Jednak bez względu na wybraną szerokość interfejsu przesłane do modułu wyświetlającego wartości muszą mieć postać 8-bitową. W związku z tym w trybie 4-bitowym transmisja jednej instrukcji lub danej musi dokonać się w dwóch cyklach - w pierwszym przesyłany jest półbajt starszy a w drugim młodszy. W układzie EasyWeb mamy podłączone wyjścia P2.4 do P2.7 do linii danych DB4 do DB7, wobec tego układ należy ustawić w trybie pracy 4 bitowej. Do wyświetlacza podłączone są linie danych DB4-DB7, trzy linie sterujące E, RS, R/W, oraz zasilanie.

Układ posiada 2 8-bitowe rejestry: rejestr instrukcji IR (stan 0 na wejściu RS), służący do przyjmowania kodów instrukcji takich jak ustawienie stanu wyświetlacza czy przesunięcie kursora, oraz rejestr danych DR (stan 1 na wejściu RS), który przyjmuje dane przesyłane na wyświetlacz.
Wyświetlacz posiada 2 linie i na każdej może wyświetlać 16 znaków. W pamięci DD_RAM dla każdej linii może przechowywać 40 znaków, pod adresem 00h-27h górna linia, zaś 40h-67h dolna linia. Przesuwanie danych za pomocą funkcji DATA_ROL_LEFT lub DATA_ROL_RIGHT odbywa się jednocześnie na obu liniach.

Opis linii wyświetlacza.

RS - odpowiada za interpretowanie danych przychodzących do sterownika wyświetlacza
0 - (stan niski) dane interpretowane jako instrukcje
1 - (stan wysoki) dane interpretowane jako adres do tablicy znaków zapisanej w pamięci ROM wyświetlacza

R/W - informuje sterownik wyświetlacza o zamiarze pisania lub czytania do wyświetlacza.
W układzie EasyWeb2 linia ta jest na stałe podłączona do masy, czyli możliwy jest tylko zapis.

E - służy do aktywowania zapisu danych do układu, aktywowana po daniu danych na linie
danych.

DB4 -DB7 - linie do przesyłania danych

DB0-DB4 - linie do przesyłania danych, nie używane podczas 4-bitowych operacji

Komendy wyświetlacza.

#define CLR_DISP 0x01 // czyści wyświetlacz
#define DISP_OFF 0x08 // wyłącza wyświetlacz
#define DISP_ON 0x0c // włącza wyświetlacz
#define DATA_ROL_LEFT 0x18 // przesuwa znaki w lewo
#define DATA_ROL_RIGHT 0x1c // przesuwa znaki w prawo
#define DD_RAM_ADDR 0x80 // ustawia kursor na linii pierwszej
#define DD_RAM_ADDR2 0xc0 // ustawia kursor na linii drugiej


Watchdog timer

WDT jest to układ, który czuwa na prawidłowym działaniem programu. Eliminuje wszelkie zawieszenia programu przez restart całego urządzenia. W programie by odczekać drgania styków używamy długiej pętli, dlatego też jesteśmy zmuszeni do wyłączenia WDT gdyż, w przeciwnym wypadku, każda pętla uznawana byłaby za zawieszenie programu i wtedy automatycznie zostałaby przerwana.

Inicjalizacja wyświetlacza

Ponieważ po włączeniu zasilania występują stany nieustalone i nie wiemy w jakim trybie jest ustawiony interfejs na początku musimy ustawić tryb pracy magistrali, czyli na tryb 4-bitowy. Czyli trzykrotnie wysyłamy do sterownika komendę inicjującą tryb 8-bitowy, a następnie komendę inicjującą tryb 4-bitowy. Po przejściu na tryb 4-bitowy, wysyłamy instrukcję włączenia wyświetlacza, następnie ustawiamy jego parametry i czyścimy wyświetlacz. Po wykonaniu wszystkich czynności możemy już wysyłać dane oraz instrukcje do wyświetlacza.

Kod programu:

#include <msp430x14x.h>
#include "lcd.h"
#include "portyLcd.h"


unsigned char i;
unsigned char znak;
int linia=1; // zmienna określająca linię: 1 -gorna ,2 -dolna
char tablica[2][40]; //tablica znaków z przeszkodami
int pozycja; //aktualna pozycja x'a
int czas; //czas w ciągu którego gracz może zmienić linię
int wynik; //ilość punktów zdobytych przez gracza

int ustawKursorNaOkreslonejPozycjiWLinii(int nr_linii, int nr_pozycji)  // funkcja, za pomocą której ustawiamy kursor na określonej pozycji w podanej linii
{
 if (nr_pozycji < 0 && nr_pozycji > 40)  // w pamięci dla każdej linii przechowywane jest miejsce na 40 pozycji (znaków), ale i tak na wyświetlaczu możemy wyświetlić 16 znaków
return -1;  // zatem prawidłowa wartość dla nr_pozycji to liczba z zakresu od 0 do 39.

 switch(nr_linii)  // nr_linii - to numer linii wyświetlacza
 {
 case 1:
  SEND_CMD(DD_RAM_ADDR  | nr_pozycji);  // ustawienie kursora na odpowiednia pozycje w pierwszej linii (oczywiście mówimy tu o wyświetlaczu ustawionym na dwie linie)
  break;
 case 2:
  SEND_CMD(DD_RAM_ADDR2 | nr_pozycji);  // ustawienie kursora na odpowiednia pozycje w drugiej linii
  break;
 default:
  return -1;  // podano nr_linii nie do zrealizowania (inny niż pierwsza czy druga linia)
 }
 return 0;
}

void ustawZnakNaOkreslonejPozycjiWPodanejLinii(int nr_linii, int nr_pozycji, char znak) // funkcja ustawiająca znak na odpowiedniej pozycji w podanej linii
{
if (-1 == ustawKursorNaOkreslonejPozycjiWLinii(nr_linii, nr_pozycji)) // wykorzystujemy wcześniej zdefiniowaną funkcję do ustawienia kursora na określonej pozycji w linii
  return;
  SEND_CHAR(znak);  // jeśli ustawienie powidło się umieszczenie odpowiedniego znaku na tej pozycji
}

void zamienLiczbe(int liczba) //funkcja zamienia liczbę na ciąg znaków i wypisuje je na ekran (na aktualnej pozycji)
{
  if (liczba/10)
      zamienLiczbe(liczba/10);
  SEND_CHAR(liczba%10+0x30);
}

void init_przeszkody() //funkcja za pomocą której inicjalizujemy tablicę z przeszkodami

{
 int i,j;
 for(j=0;j<2;j++)
 for(i=0;i<40;i++)
      tablica[j][i]=' ';

 tablica[0][4]='0';
 tablica[0][10]='0';
 tablica[0][11]='0';
 tablica[0][12]='0';
 tablica[0][20]='0';
 tablica[0][21]='0';
 tablica[0][33]='0';

 tablica[1][15]='0';
 tablica[1][16]='0';
  tablica[1][17]='0';
 tablica[1][26]='0';
 tablica[1][27]='0';
 tablica[1][37]='0';

 for(j=0;j<2;j++)
 for(i=0;i<40;i++)
      if(tablica[j][i]=='0') ustawZnakNaOkreslonejPozycjiWPodanejLinii(j+1, i, tablica[j][i]); //wstawiamy znaki do pamięci wyświetlacza
}

int rysujXa(int rol) //w przypadku rol=0 lub rol=-1 funkcja rysuje x'a (pojazd którym steruje gracz)

na odpowiedniej linii w zależności od wciśniętego przycisku, w pozostałych przypadkach następuje przesunięcie ekranu w prawo i odrysowanie x'a (zwraca 0) lub znaku # jeżeli x zderzył się z przeszkodą (zwraca -1)

{
 if (0==rol||-1==rol) //gracz wcisnął przycisk
 {
  int linia_pom;
  if(rol==0) linia_pom=1; else linia_pom=2;
  if(linia!=linia_pom) { //sprawdza czy wciśnięto przycisk inny niż linia na której znajduje się x
      ustawZnakNaOkreslonejPozycjiWPodanejLinii(linia, pozycja , ' ');
      linia=linia_pom;
      if (tablica[linia-1][pozycja] == '0')
      {
        ustawZnakNaOkreslonejPozycjiWPodanejLinii(linia, pozycja , '#'); //nastąpiło zderzenie, wstawiamy znak #
        return -1;
      }
      ustawZnakNaOkreslonejPozycjiWPodanejLinii(linia, pozycja , 'x'); //nie nastąpiło zderzenie, odrysowujemy znak x
  }
 }
 else //po określonym czasie następuje przesunięcie w prawo
 {
      int i;
      ustawZnakNaOkreslonejPozycjiWPodanejLinii(linia, pozycja, ' '); //kasujemy x'a, wstawiając w jego miejscie spacje
      for (i=0; i<rol; ++i) //przesuwamy ekran w prawo rol ilość razy i odpowiednio zmieniamy pozycję x'a
      {
        SEND_CMD(DATA_ROL_RIGHT); //przesunięcie w prawo
        --pozycja;
        if(pozycja==-1) pozycja=39;

      }

      if (tablica[linia-1][pozycja] == '0')
      {
        ustawZnakNaOkreslonejPozycjiWPodanejLinii(linia, pozycja , '#'); //nastąpiło zderzenie, rysujemy znak #
        Delayx100us(250); //czekamy chwilę czasu by gracz mógł dostrzec, że nastąpiło zderzenie
        return -1;
      }
      ustawZnakNaOkreslonejPozycjiWPodanejLinii(linia, pozycja , 'x');//nie nastąpiło zderzenie, rysujemy x'a

//jeżeli gracz ominą przeszkodę zwiększamy liczbę punktów
      int pom=linia-1;
      pom=(pom)?0:1;
      if (tablica[pom][pozycja] == '0') wynik++;
 }
      return 0;
}

 void main( void )
{

WDTCTL=WDTPW+ WDTHOLD; // zatrzymanie WDT

InitPortsLcd(); // inicjalizacja portów
InitLCD();  // inicjalizacja LCD
clearDisplay(); // czyszczenie wyświetlacza

P4DIR &= ~BIT4; // konfigurowanie linii P4.4 (przycisk B1) jako wejście
P4DIR &= ~BIT5; // konfigurowanie linii P4.4 (przycisk B1) jako wejście\P4DIR &= ~BIT5; // konfigurowanie linii P4.4 (przycisk B1) jako wejście
P4DIR &= ~BIT6; // konfigurowanie linii P4.4 (przycisk B1) jako wejście

// kod odpowiedzialny za umieszczenie napisu 'ABCD' na pierwszej linii wyświetlacza na pozycjach od 1 do 4 (przymuję określenie tutaj pozycji wyświetlacza jaka liczbę od 1 do 16)

while(1) {

//wyświetlenie napisu START
SEND_CMD(CLR_DISP);
ustawKursorNaOkreslonejPozycjiWLinii(1, 4);
 SEND_CHAR('S');
 Delayx100us(250);
 SEND_CHAR('T');
 Delayx100us(250);
 SEND_CHAR('A');
 Delayx100us(250);
 SEND_CHAR('R');
 Delayx100us(250);
 SEND_CHAR('T');
 Delayx100us(250);
 SEND_CHAR('=');
 Delayx100us(70);
 SEND_CHAR('=');
 Delayx100us(70);
 SEND_CHAR('>');
 Delayx100us(150);
SEND_CMD(CLR_DISP);

init_przeszkody(); //inicjalizacja przeszkód

int koniec=0,licznik,win=0;
 wynik=0;

czas=400; //początkowa ilość czasu, po którym nastąpi przesunięcie w prawo
pozycja=15;    //początkowa pozycja pozycja x'a
linia=1;

while(1)
      {
         licznik=0;
         for(;;)
         {
            if( (P4IN & BIT4) ==0 )    // sprawdzamy stan przycisku
                 koniec=rysujXa(0);
             else if( (P4IN & BIT5) ==0 ) //sprawdzamy stan przycisku 2
                 koniec=rysujXa(-1);

            if(koniec==-1) break; //nastąpiło zderzenie, więc wychodzimy z pętli

//odczekanie niedużego odstępu czasu(w zależności od wartości czas) po których nastąpi sprawdzenie czy 1 z przycisków został wciśnięty
            if(czas<20) {
             Delayx100us(1);
             licznik+=1;
            }
            else {
              Delayx100us(20);
              licznik+=20;
            }
            if(licznik>=czas) break; //jeżeli suma niedużych odstępów czasu wyniesie co najmniej wartość czas, następuje wyjście z pętli a następnie przesunięcie w prawo
         }
         if(koniec==-1) break; //nastąpiło zderzenie, więc wychodzimy z pętli

         koniec=rysujXa(1); //przesunięcie w prawo
         if(koniec==-1) break; //nastąpiło zderzenie, więc wychodzimy z pętli

//zmniejszamy czas w którym gracz może nacisnąć przycisk
         if(czas>100) czas-=10;
         else if(czas<=100&&czas>60) czas-=5;
         else if(czas<=60&&czas>1) czas--;

         if(wynik>=50) {win=1;break;} //jeżeli ilość ominiętych jest >= od 50 gracz wygrywa, wychodzimy z pętli
      }
SEND_CMD(CLR_DISP);
ustawKursorNaOkreslonejPozycjiWLinii(1, 4);

//wypisanie komunikatu o wygranej lub przegranej
if(win||wynik>=50) {
 SEND_CHAR('Y');
 SEND_CHAR('o');
 SEND_CHAR('U');
 SEND_CHAR(' ');
 SEND_CHAR('W');
 SEND_CHAR('i');
 SEND_CHAR('N');
}
else {
 SEND_CHAR('G');
 SEND_CHAR('A');
 SEND_CHAR('M');
 SEND_CHAR('E');
 SEND_CHAR(' ');
 SEND_CHAR('O');
 SEND_CHAR('V');
 SEND_CHAR('E');
 SEND_CHAR('R');

}

//wypisanie ilości zdobytych punktów
ustawKursorNaOkreslonejPozycjiWLinii(2,4);
 SEND_CHAR('P');
 SEND_CHAR('U');
 SEND_CHAR('N');
 SEND_CHAR('K');
 SEND_CHAR('T');
 SEND_CHAR('Y');
 SEND_CHAR(':');
 SEND_CHAR(' ');
 
 zamienLiczbe(wynik); //zamiana i wypis ilość punktów

while(1) if( (P4IN & BIT6) ==0 ) break; //czekamy aż użytkownik naciśnie przycisk 3, po którym gra rozpocznie się od początku
}
}



Wyszukiwarka

Podobne podstrony:
04 instrukcja dla gracza A, studia kierunek administracja, gra negocjacyjna
Wykład 04
04 22 PAROTITE EPIDEMICA
04 Zabezpieczenia silnikówid 5252 ppt
Wyklad 04
Wyklad 04 2014 2015
04 WdK
04) Kod genetyczny i białka (wykład 4)
2009 04 08 POZ 06id 26791 ppt
2Ca 29 04 2015 WYCENA GARAŻU W KOSZTOWEJ
04 LOG M Informatyzacja log
04 Liczby ujemne i ułamki w systemie binarnym
UE i ochrona srodowiska 3 04 2011
04 QueryByExample Access

więcej podobnych podstron