Politechnika Lubelska w Lublinie |
Laboratorium Układów Mikroprocesorowych |
||
|
Ćwiczenie nr 8 |
||
Jarosław Kucharzewski |
Semestr IX |
Grupa ED9.8 |
Rok akademicki 2007/2008 |
Temat ćwiczenia: Wyświetlacz i klawiatura na mikrokontrolerze ATMega32 |
Data wykonania: 11.12.07 |
Ocena: |
1. Cel ćwiczenia
Celem ćwiczenia było zapoznanie się z budową i obsługą mikrokontrolera ATMega32 oraz modułu wyświetlacza LCD na sterowniku HD44780.
2. Wykonanie ćwiczenia
Program miał za zadanie wyświetlać znak przypisany danemu przyciskowi z klawiatury na wyświetlaczu LCD, kiedy przycisk zostanie wciśnięty. W wypadku wciśnięcia dwóch przycisków miał być wyświetlony kod błędu. Ponadto na diodach podłączonych do jednego z portów pokazywał się kod bitowy znaku, który jest przesyłany na wyświetlacz. Program opierał się na trzech funkcjach: klawiatura, wyświetlacz i czekaj. Na początku ustawiliśmy tryb pracy portu A tak, aby jego starsza część była wyjściami podłączonymi do wierszy klawiszy, a młodsza wejściami podłączona do kolumn. Port B sterował diodami i był ustawiony jako wyjście, port D był podłączony do wyświetlacza tak, że pierwsza linia podawała sygnał RS, druga E a cztery młodsze były liniami danych. Cały port pracował więc jako wyjście. Następnie przesłaliśmy do wyświetlacza zestaw instrukcji sterujących podanych przez producenta. Wyświetlacz ustawialiśmy na pracę 4-bitową więc dane instrukcji były przesyłane w dwóch etapach.
Funkcja klawiatura zwracała kod wciśniętego klawisza. Przypisywała ona do starszej części portu A 0 na odpowiednią linię odpowiadającą jednemu z czterech wierszy klawiszy, a następnie sczytywała wszystkie kolumny podłączone do młodszych linii portu A. W ten sposób znaliśmy wiersz i kolumnę klawisza. W wypadku wykrycia innej sekwencji bitów niż zakładana i odpowiadająca wciśniętemu jednemu lub żadnemu klawiszowi, funkcja wykrywała błąd i omijała sprawdzanie pozostałych wierszy. Sprawdzanie wciśnięcia dwóch klawiszy z różnych kolumn realizowałem przez iloczyn zmiennej odpowiadającej za wiersz poprzedni ze zmienną do której sczytywałem kod z wiersza obecnego. Jeśli iloczyn był różny od zera oznaczało to, że nastąpiło wciśnięcie dwóch klawiszy jednocześnie i funkcja wystawiała kod błędu. Jeśli nie, następowało sprawdzenie, która zmienna jest różna od zera i ta była zwracana dalej jako kod wciśniętego klawisza.
W pętli głównej wystawiałem kod zwracany przez funkcję klawiatura na port B (diody) i jako zmienną wejściową funkcji wyświetlacz. Funkcja ta wysyłała otrzymany kod znaku na wyświetlacz. Starszą część instrukcji zawierającej znak wysyłałem maskując młodsze bity kodu znaku i dodając odpowiednią część sterującą sygnałami RS i E. W ten sposób na liniach 4-7 portu D miałem dane a 1 i 2 sygnały sterujące. Młodszą część otrzymywałem przez przesunięcie młodszej części kodu znaku na starsze bity (pomnożenie przez 16) a następnie dodanie części sterującej sygnałami RS i E. Na koniec należało dodać odpowiednie zwłoki czasowe realizowane przez funkcję czekaj powtarzającą rozkaz NOP w pętli for.
#include <avr/io.h>
#define ROW1 0b01111111;
#define ROW2 0b10111111;
#define ROW3 0b11011111;
#define ROW4 0b11101111;
#define key0 0x30;
#define key1 0x31;
#define key2 0x32;
#define key3 0x33;
#define key4 0x34;
#define key5 0x35;
#define key6 0x36;
#define key7 0x37;
#define key8 0x38;
#define key9 0x39;
#define keyA 0x41;
#define keyB 0x42;
#define keyC 0x43;
#define keyD 0x44;
#define keyE 0x45;
#define keyF 0x46;
#define none 0x00;
#define error 0x21;
void czekaj(int czas)
{int i;
for (i=0;i<czas;i++)
asm ("nop");
};
void wyswietlacz(int kod)
{if (kod!=0)
{czekaj(1000);
PORTD=0b00000011+(kod & 0b11110000); //transmisja starszych bitow - E=1
czekaj(1000);
PORTD=(PORTD & 0b11111101); //transmisja starszych bitow - E=0, zapis
czekaj(1000);
PORTD=0b00000011+kod*16; //transmisja mlodszych bitow - E=1
czekaj(1000);
PORTD=(PORTD & 0b11111101); //transmisja mlodszych bitow - E=0, zapis
};
};
int klawiatura()
{int kod=0,kod2=0,key;
PORTA=ROW1; //0b01111111;
key=PINA;
czekaj(1000);
switch (key)
{case 0b01111111:kod=none;break;
case 0b01111110:kod=key1;break;
case 0b01111101:kod=key2;break;
case 0b01111011:kod=key3;break;
case 0b01110111:kod=key4;break;
default:kod=error;
};
If (kod!=0x21)
{PORTA=ROW2; //0b10111111;
key=PINA;
czekaj(1000);
switch (key)
{case 0b10111111:kod2=none;break;
case 0b10111110:kod2=key5;break;
case 0b10111101:kod2=key6;break;
case 0b10111011:kod2=key7;break;
case 0b10110111:kod2=key8;break;
default:kod2=error;
};
if (kod*kod2==0)
{if (kod==0) kod=kod2;
};
else kod=error;
};
If (kod!=0x21)
{PORTA=ROW3; //0b11011111;
key=PINA;
czekaj(1000);
switch (key)
{case 0b11011111:kod2=none;break;
case 0b11011110:kod2=key9;break;
case 0b11011101:kod2=key0;break;
case 0b11011011:kod2=keyA;break;
case 0b11010111:kod2=keyB;break;
default:kod=error;
};
if (kod*kod2==0)
{if (kod==0) kod=kod2;
};
else kod=error;
};
If (kod!=0x21)
{PORTA=ROW4; //0b11101111;
key=PINA;
czekaj(1000);
switch (key)
{case 0b11101111:kod2=none;break;
case 0b11101110:kod2=keyC;break;
case 0b11101101:kod2=keyD;break;
case 0b11101011:kod2=keyE;break;
case 0b11100111:kod2=keyF;break;
default:kod=error;
};
if (kod*kod2==0)
{if (kod==0) kod=kod2;
};
else kod=error;
};
return kod;
};
void main()
{DDRB=0b11111111;
DDRD=0b11111111;
DDRA=0b11111111;
PORTA=0b11111111;
DDRA=0b11110000;
//ustawienie interfejsu 4-bitowego
PORTD=0b00100010; //transmisja starszych bitow - E=1
czekaj(1000);
PORTD=0b00100000; //transmisja starszych bitow - E=0, zapis //włączenie wyswietlacza, kursora, wylaczenie migania
czekaj(1000);
PORTD=0b00000010; //transmisja starszych bitow - E=1
czekaj(1000);
PORTD=0b00000000; //transmisja starszych bitow - E=0, zapis
czekaj(1000);
PORTD=0b11100010; //transmisja mlodszych bitow - E=1
czekaj(1000);
PORTD=0b11100000; //transmisja mlodszych bitow - E=0, zapis //czyszczenie wyswietlacza
czekaj(1000);
PORTD=0b00000010; //transmisja starszych bitow - E=1
czekaj(1000);
PORTD=0b00000000; //transmisja starszych bitow - E=0, zapis
czekaj(1000);
PORTD=0b00010010; //transmisja mlodszych bitow
czekaj(1000);
PORTD=0b00010000; //transmisja mlodszych bitow - E=0, zapis
//konfiguracja wyswietlacza (kierunek+1, przesow-brak)
czekaj(1000);
PORTD=0b00000010; //transmisja starszych bitow - E=1
czekaj(1000);
PORTD=0b00000000; //transmisja starszych bitow - E=0, zapis
czekaj(1000);
PORTD=0b01100010; //transmisja mlodszych bitow - E=1
czekaj(1000);
PORTD=0b01100000; //transmisja mlodszych bitow - E=0, zapis
while (1)
{int kod;
kod=klawiatura();
PORTB=kod;
wyswietlacz(kod);
};
};