background image

 

Politechnika Lubelska 

 

Wydział Elektrotechniki i 

Informatyki 

 
 
 

 

Laboratorium Układów Mikroprocesorowych 

 
 

 
 
 
 
 
 

Temat  :  Obsługa  klawiatury  matrycowej  oraz  wyświetlacza 
 

 

LCD 

 
 
 

 
 
 

 

Keller Jacek 
 

 
 
 
 
 

Motycz Leśny dn. 09.12.2007 

 

background image

 

Cel ćwiczenia 

Celem ćwiczenia była obsługa za pomocą mikrokontrolera AVR (ATMEGA32) klawiatury 
matrycowej 4x4 oraz wyświetlacza LCD 2x16 w języku C. 

 
 

Obsługa klawiatury 

 

Sposób podłączenia klawiatury do mikrokontrolera: 

 

 
Dokładny port, do którego jest podłączona klawiatura został zdefiniowany w programie: 

 
 

#define klawiatura PORTA 

 

#define klawiatura_DDR DDRA 

 

#define klawiatura_PIN PINA 

 
 
Obsługa klawiatury polega na wystawieniu stanu logicznego L na danej kolumnie (na 
pozostałe kolumny i wiersze są skonfigurowane jako wejścia) a następnie odczytywaniu na 
którym z wierszy pojawi się stan L spowodowanym przyciśnięciem jednego z przycisków w 
kolumnie. Tym sposobem sterowane są pozostałe trzy kolumny. 
Realizacja programowa została dokonana za pomocą konstrukcji typu switch. 
Wykrywanie wciśniętych dwóch lub więcej przycisków  (nie w jednym wierszu) odbywa się 
poprzez sprawdzenie warunku czy w danym wierszu występuje więcej niż jeden stan L przy 
jednoczesnym wyzwoleniu stanu L na wszystkich kolumnach. Jeżeli tak jest tzn. że wciśnięto 
więcej niż jeden przycisk. 
Sprawdzanie czy w wierszu zostały wciśnięte dwa lub więcej przyciski odbywa się na 
zasadzie sprawdzenia czy wystąpił warunek odpowiadający naciśniętemu jednemu z czterech 
przycisków lub nie wciśniętemu żadnemu. Jeżeli jeden z powyższych stanów nie wystąpił tzn. 
ż

e wciśnięto więcej niż jeden przycisk w wierszu. W takich przypadkach funkcja 

sprawdzająca stan klawiatury zwraca wartość 0xff.

 

 
 

background image

 

int key(void) 

    klawiatura_DDR=0b00001111; 
    klawiatura=0b11110000; 

       // sprawdzenie czy dwa lub wiecej wcisniete  

 

 

 

 

 

//(nie dotyczy sprawdzenia w jednym wierszu) 

    if ((klawiatura_PIN!=0b11100000 )&& (klawiatura_PIN!=0b11010000) &&  
 

(klawiatura_PIN!=0b10110000) && (klawiatura_PIN!=0b01110000) && 

 

(klawiatura_PIN!=0b11110000)) return 0xff;     //czyli wcisnieto ponad dwa 

 
klawiatura_DDR=0b0001000;  //zeby nie bylo zwarcia w momenie wcieniecia klawiszy w 
 

 

 

 

 //tym samym wierszu 

klawiatura=0b11110111; 

 //kolumna1  11110111 

  
switch(klawiatura_PIN) 
    { 
      case 0b11100111 

: return 'C'; break; 

// kolumna 1, wiersz 4 

 

      case 0b11010111 

: return '8'; break; 

// kolumna 1, wiresz 3 

 

      case 0b10110111 

: return '4'; break; 

// kolumna 1, wiersz 2 

 

      case 0b01110111 

: return '0'; break; 

// kolumna 1, wiersz 1 

 

      case 0b11110111 

: break; 

 

 

// nic nie wcisnieto 

      default : return 0xff;                        //inna wartosc tzn ze wcisniete 
 

 

 

 

 

 

 

 

//dwa lub wiecej w wierszu 

    }                       

 

 

 
 
 klawiatura_DDR=0b0000100;  
 klawiatura=0b11111011; 

 

//kolumna2 

 switch(klawiatura_PIN) 
    { 
      case 0b11101011   : return 'D'; break;   

// kolumna 2, wiersz 4 

      case 0b11011011 

: return '9'; break; 

// kolumna 2, wiersz 3 

      case 0b10111011 

: return '5'; break; 

// kolumna 2, wiersz 2 

      case 0b01111011 

: return '1'; break; 

// kolumna 2, wiersz 1 

      case 0b11111011 

: break; 

 

 

// nic nie wcisnieto 

      default : return 0xff;                     
    } 
 
 
 klawiatura_DDR=0b0000010;   
 klawiatura=0b11111101; 

 

//kolumna3 

 switch(klawiatura_PIN) 
    { 
     case 0b11101101 

: return 'E'; break; 

// kolumna 3, wiersz 4 

     case 0b11011101 

: return 'A'; break; 

// kolumna 3, wiersz 3  

 

     case 0b10111101 

: return '6'; break; 

// kolumna 3, wiersz 2 

 

     case 0b01111101 

: return '2'; break; 

// kolumna 3, wiersz 1 

     case 0b11111101 

: break; 

 

 

// nic nie wcisnieto 

     default : return 0xff; 
    } 
 
 
 klawiatura_DDR=0b0000001; 
 klawiatura=0b11111110; 

 

//kolumna4 

 switch(klawiatura_PIN) 
    { 
     case 0b11101110 

: return 'F'; break; 

 

// kolumna 4, wiersz 4 

     case 0b11011110 

: return 'B'; break; 

 

// kolumna 4, wiersz 3 

     case 0b10111110 

: return '7'; break; 

 

// kolumna 4, wiersz 2 

     case 0b01111110 

: return '3'; break; 

 

// kolumna 4, wiersz 1 

     case 0b11111110 

: break; 

 

            // nic nie wcisnieto 

     default : return 0xff; 
    } 
 return 0x00; 

 
 
 

background image

 

Należy zauważyć, że aby wyeliminować możliwość zwarcia w porcie (stan w którym 
przyciśnięte są dwa przyciski w jednym wierszu, czyli zwarcie dwóch kolumn gdzie na jednej 
kolumnie jest stan H a natomiast na drugiej stan L) trzeba określić aby stan H na kolumnach 
był wymuszany nie poprzez wewnętrzny przerzutnik D zawarty w strukturze portu (sterowany 
sygnałem WPx) a poprzez wewnętrzny rezystor podciągający do zasilania, w tym momencie 
rezystor ogranicza płynący prąd 
Stan ten osiągamy, gdy na wyjściu przerzutnika D sterowanego linią WDx jest stan L a na 
wyjściu przerzutnika D sterowanego sygnałem WPx będzie panował stan H (dodatkowo bit 
PUD (sterowany z rejestru SFIOR) powinien mieć wartość L. Czyli wszystkie bity portu do 
którego podłączona jest klawiatura powinny być skonfigurowane jako wejścia a do bitów ich 
rejestru wyjściowego powinny być wpisane stany H  oprócz bitu na którym będzie 
wystawiany stan L: 
 

klawiatura_DDR=0b0001000;  //zeby nie bylo zwarcia w momenie wcieniecia klawiszy w 
 

 

 

 

 //tym samym wierszu 

klawiatura=0b11110111; 

 //kolumna1  11110111 

 
 Sytuację wyjaśnia schemat struktury portu noty katalogowej ATMEGA32: 
 

 

 
 
 
 

background image

 

Obsługa wyświetlacza LCD 

 

Wyświetlacz LCD pracuje trybie 4 bitowym. Najstarsze 4 bity zostały podłączone do 

najstarszych czterech bitów portu mikrokontrolera, który jest zdefiniowany jako LED_H w 
programie: 
 

#define EN 1   //jako bit1 portu gdzie podlaczono LCD_H 
#define RS 0   //jako bit0 portu gdzie podlaczono LCD_H 
 
#define LCD_H PORTD 
#define LCD_H_DDR DDR 

 
Sygnały EN oraz RS zostały zdefiniowane jako podłączone do tego samego portu tylko, że 
dwóch najmniej znaczących bitów. 
Sterowanie zapisem do LCD odbywa się za pomocą bitów EN (Enable) oraz RS (Register 
Select) oraz starszej części LED_H, która pracuje jako magistrala dla LCD. 
Dokładny sposób sterowania opisują przebiegi czasowe opisane w dokumentacji sterownika 
HD44780: 
 

 

 
 
Taki sposób sterowania wymaga aby zmieniać tylko bity portu do którego jest podłączony 
LCD nie naruszając jego pozostałej części. Ten problem został rozwiązany poprzez 
maskowanie portu. 
 

void LCD_zapis(char dana) 
  { SET_EN; 
   LCD_H = ((LCD_H & 0b00001111) | (dana & 0b11110000));     // zapis pierwszej 
   

 

 

 

 

 

 

 

 

//połówki bajtu 

   CLR_EN; 
   SET_EN; 
   LCD_H = ((LCD_H & 0b00001111) | ((dana & 0b00001111) << 4)); // 2 połówka 
    CLR_EN; 
    delay(1); 
   } 
 

 

background image

 

Instrukcje sterujące bitami EN oraz RS zostały zdefiniowane jako SET_EN, CLR_EN, 
SET_RS, CLR_RS dla większej przejrzystości programu: 
 

#define SET_EN   LCD_H = LCD_H | (1 << EN) 
#define CLR_EN   LCD_H = LCD_H & ~(1 << EN) 
 
#define SET_RS  LCD_H = LCD_H | (1 << RS) 
#define CLR_RS  LCD_H = LCD_H & ~(1 << RS) 
 

Zapis instrukcji oraz danych odbywa się poprzez procedury sterujące bitem RS a następnie 
odwołaniu do procedury bezpośredniego zapisu do LCD (LCD_zapis): 
 

void LCD_instr(char dana) 
  { CLR_RS; 
    LCD_zapis(dana); 
  } 
 
void LCD_dana(char dana) 
  { SET_RS; 
    LCD_zapis(dana); 
  } 
 

Inicjalizacja wyświetlacza LCD odbywa się za pomocą wysłania sekwencji instrukcji do 
niego zgodnych z zaleceniami z datasheet sterownika HD44780 (oczywiście pomijane jest 
sprawdzanie flagi BF (Busy Flag), w zastępstwie zastosowano procedurę czekania 
określonego czasu: 

 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

background image

 

Działanie programu. 

W pętli głównej konstrukcja switch wywołuje funkcję sprawdzającą stan klawiszy i na tej 
podstawie zapala na diodach LED kod binarny odpowiadający wciśniętemu przyciskowi a 
następnie wyświetla na wyświetlaczu LCD jaki klawisz został naciśnięty. 
W przypadku wciśnięcia więcej niż jednego klawisza zapalają się wszystkie diody a na LCD 
zostaje wyświetlona stosowna informacja. 
W czasie gdy żaden z przycisków nie jest wciśnięty diody są wygaszone, natomiast na LCD 
wyświetlony jest komunikat aby nacisnąć przycisk: 

 
 
while (1) 
   { 
     switch(key()) 
       { 
 

     case '0' : {LED=0;  LCD_text_WCISNIETO(); LCD_text("0");LCD_spacje();} break;

 

 

 

     case '1' : {LED=1;  LCD_text_WCISNIETO(); LCD_text("1");LCD_spacje();} break; 

 

     case '2' : {LED=2;  LCD_text_WCISNIETO(); LCD_text("2");LCD_spacje();} break;

 

 

 

     case '3' : {LED=3;  LCD_text_WCISNIETO(); LCD_text("3");LCD_spacje();} break; 

 

     case '4' : {LED=4;  LCD_text_WCISNIETO(); LCD_text("4");LCD_spacje();} break; 

 

     case '5' : {LED=5;  LCD_text_WCISNIETO(); LCD_text("5");LCD_spacje();} break; 

 

     case '6' : {LED=6;  LCD_text_WCISNIETO(); LCD_text("6");LCD_spacje();} break;

 

 

 

     case '7' : {LED=7;  LCD_text_WCISNIETO(); LCD_text("7");LCD_spacje();} break;

 

 

 

     case '8' : {LED=8;  LCD_text_WCISNIETO(); LCD_text("8");LCD_spacje();} break; 

 

     case '9' : {LED=9;  LCD_text_WCISNIETO(); LCD_text("9");LCD_spacje();} break; 

 

     case 'A' : {LED=10; LCD_text_WCISNIETO(); LCD_text("A");LCD_spacje();} break; 

 

     case 'B' : {LED=11; LCD_text_WCISNIETO(); LCD_text("B");LCD_spacje();} break; 

 

     case 'C' : {LED=12; LCD_text_WCISNIETO(); LCD_text("C");LCD_spacje();} break; 

 

     case 'D' : {LED=13; LCD_text_WCISNIETO(); LCD_text("D");LCD_spacje();} break; 

 

     case 'E' : {LED=14; LCD_text_WCISNIETO(); LCD_text("E");LCD_spacje();} break; 

 

     case 'F' : {LED=15; LCD_text_WCISNIETO(); LCD_text("F");LCD_spacje();} break;

 

 

 

 

 

     case 0xff :{LED=255;LCD_text_WCISNIETO(); LCD_text("wiecej");} break; 

 

     case 0x00 :{LED=0;  LCD_instr(0b00000010); LCD_text("Wcisnij cos   ");} break; 

 

    } 

   } 

 
 

void LCD_spacje(void) 
 { LCD_text("     ");} 
 
void LCD_text_WCISNIETO(void) 
 { LCD_instr(0b00000010); LCD_text("Wcisnieto ");}