Obsługa Klawiatury Wieloprzyciskowej


10
Ocena: None Średnia: 10 (2 głosujących)

W układach mikroprocesorowych bardzo często w roli interfejsu między urządzeniem a jego użytkownikiem wykorzystujemy klawiaturę złożoną z przycisków uSwitch. Gdy jest kilka przycisków to wystarczy proste podłączenie między portem mikrokontrolera a masą, dla większej liczby klawiszy wygodnie będzie zrobić klawiaturę matrycową, bo uzyskamy wtedy większą liczbę klawiszy a wykorzystamy mniej pinów procesora. Przedstawione tutaj procedury dotyczą obsługi tych dwóch typów klawiatury.

Język Bascom AVR

Poniżej przedstawiona jest prosta procedura odczytu czterech przycisków podłączonych do jednego portu, niewrażliwa na drgania styków i pozwalająca ustawić różny czas reakcji przy pojedynczym kliknięciu i podczas trzymania klawisza:

Przyciski:
Sw = PIND And &B11110000             'maskowanie nieużywanych pinów
 
If Sw <> &B11110000 And Stan_sw = Sw Then
    Incr Licznik_sw
    If Licznik_sw = 100 Then
      Licznik_sw = 0
      Select Case Stan_sw
        Case &B01110000:                                   
           'tutaj to co będzie po kliknięciu S1   
        Case &B10110000:                                   
           'tutaj to co będzie po kliknięciu S2 
        Case &B11010000: 
           'tutaj to co będzie po kliknięciu S3                              
        Case &B11100000:         
           'tutaj to co będzie po kliknięciu S4
        Case &B00110000:         
           'tutaj to co będzie po kliknięciu S1 i S2 razem        
      End Select
    End If
  Else
    Stan_sw = Sw
    Licznik_sw = 80
  End If
Return

Procedura dotyczy podłączenia jak na rysunku poniżej, zakładamy że inne piny tego portu są wykorzystywane w dowolny sposób i nie mamy wpływu na ich stany logiczne podczas odczytu klawiatury:

Jak widać przyciski są podłączone do starszych 4 bitów portu D mikrokontrolera (żeby nie było za prosto). Musimy zatem uniezależnić się od zmieniających się stanów logicznych na pozostałych 4 bitach tego portu aby nie było problemów z klawiaturą. Wykonujemy to w pierwszej linijce procedury przypisując do zmiennej Sw(byte) wartość całego portu D ale z wyzerowanymi za pomocą polecenia And &B11110000 wartościami najmłodszych bitów (starsze 4 są bez zmian). Jeżeli nic nie zostało naciśnięte to stan odczytu przycisków wynosi zatem &B11110000, bo żaden nie zwarł do masy pinu procesora. Sprawdzane jest to w pierwszej instrukcji warunkowej i w spoczynku kiedy nic nie naciskamy to zawsze wykonują się polecenia po instrukcji Else, czyli przypisywanie aktualnego Stanu klawiatury do zmiennej Stan_sw, która przechowuje poprzednią wartość stanu przycisków, oraz ustawianie Licznik_sw = 80 na określoną wartość.

Gdy Przycisk został wciśnięty to warunek sprawdza jeszcze dodatkowo czy stan klawisza jest taki jak był poprzednio (czy to na przykład nie jest drganie styku) i jeśli tak to zwiększany jest stan licznika (Licznik_sw). Gdy licznik dojdzie do ustalonej wartości (przycisk odpowiednio długo trzymany) to zostanie wykonana akcja dla klawiatury w zależności od tego co zostało kliknięte. Załatwia to wewnętrzna instrukcja Select Case Stan_sw, która wykonuje odpowiedni Case w zależności od stanu klawiszy. Dla przykładu stan &B01110000 odpowiada za kliknięcie przycisku S1 (zero na pinie PD.7), a &B00110000 odpowiada jednoczesnemu wciśnięciu S1 i S2 (zera na pinach PD.7 i PD.6)

Tłumaczenia mogą jeszcze wymagać wartość zmiennej Licznik_sw pojawiające się w dwóch miejscach w procedurze. Zależą one od częstotliwości wywoływania procedury obsługi klawiatury przez program, oraz od żądanego czasu reakcji klawisza na przyciskanie. Wartości te zostały dobrane dla procedury wywoływanej co 4ms. Podczas spoczynku gdy nic nie jest naciskane zmienna Licznik_sw ma wartość 80, a podczas naciśnięcia przycisku jej wartość jest zwiększana aż do 100 po czym następuje reakcja na naciśnięcie, gdy Licznik_sw nie urośnie do 100 zanim puścimy przycisk to zostanie ustawiony znów na 80. Różnica między tymi wartościami pomnożona przez czas odstępu między wywołaniami procedury daje czas reakcji na naciśnięcie przycisku (w tym przypadku: (100-80)*4ms = 80ms). Gdy natomiast licznik urośnie do 100 to jego wartość zostanie wyzerowana i wykona się obsługa klawiatury. Dalsze trzymanie klawisza będzie teraz zwiększało licznik od 0 a zatem podczas trzymania klawisza reakcja nastąpi co 100*4ms=400ms. W efekcie po pierwszym wciśnięciu przycisk zareaguje po 80ms a gdy trzymamy ciągle to co każde 400ms.

Kiedy potrzebujemy większej liczby klawiszy to przeważnie wybór pada na klawiaturę matrycową, podobną do tej na rysunku poniżej(cztery młodsze bity są wejściami, a cztery starsze wyjściami i należy je podłączyć poprzez rezystory np. 1k):

Przy takim ustawieniu jak nie trudno zauważyć nie da się odczytać od razu całej klawiatury. Najprościej jest przeskanować całą klawiaturę a wynik zapisać do 16-bitowej zmiennej typu Word. Mając już stan klawiszy można skorzystać z procedury działającej analogicznie jak wyżej. Skanowanie klawiatury może się odbywać za pomocą procedury:

Matrycowka:
  Klawisze = 0
  For Wiersz = 4 To 7
    Portd = Portd Or &B11111111
    Portd.Wiersz = 0
    Shift Klawisze , Left , 4
    Stan_Wiersz = Pind And &B00001111
    Klawisze = Klawisze + Stan_Wiersz
  Next Wiersz
Return

Procedura ta odczytuje wszystkie przyciski i zapisuje ich stan do 16-bitowej zmiennej Klawisze, jej bity począwszy od najstarszego odpowiadają klawiszom w kolejności: S4, S3, S2, S1, S8, S7, S6, S5, S12, S11, S10, S9, S16, S15, S14, S13. Odczyt przebiega następująco: Za pomocą pętli For zmienna pomocniacza Wiersz zmienia swoje wartości od 4 do 7 co odpowiada ustawieniu stanu niskiego po kolei na pinach PD.4 do PD.7. Jednocześnie podczas gdy kolejne piny przyjmują stan niski z pozostałych 4 młodszych pinów portu odczytywany jest stan 4 przycisków i wpisywany do zmiennej Klawisze, potem bity są przesuwane w lewo o 4 pozycje (Shift Klawisze , Left , 4) aby kolejne 4 przyciski zapisały się na wolnych miejscach w zmiennej Klawisze. Mówiąc w skrócie odczyt klawiatury jest dynamiczny, ustawiamy niski stan logiczny na jednym wierszu, po czym odczytujemy na które młodsze bity portu D stan ten się przeniósł. Potem ustawiamy 0 w drugim wierszu i znowu odczytujemy młodsze bity. Bezpośrednio po odczycie klawiatury musimy jeszcze zinterpretować stan klawiatury, wykonujemy to za pomocą procedury analogicznej jak przy zwykłej klawiaturze:

Przyciski:
If Klawisze <> &B1111111111111111 And Stan_sw = Klawisze Then
    Incr Licznik_sw
    If Licznik_sw = 56 Then
      Licznik_sw = 0
      Select Case Stan_sw
        Case &B1111111111111110:
             'tutaj akcja klawisza S13
        Case &B1111111111111101: 
             'tutaj akcja klawisza S14
        Case &B1111111111111011:
        Case &B1111111111110111: 
        Case &B1111111111101111: 
        Case &B1111111111011111: 
        Case &B1111111110111111: 
        Case &B1111111101111111:
        Case &B1111111011111111: 
        Case &B1111110111111111:
        Case &B1111101111111111: 
        Case &B1111011111111111: 
        Case &B1110111111111111: 
        Case &B1101111111111111: 
        Case &B1011111111111111: 
        Case &B0111111111111111: 
      End Select    
    End If
  Else
    Stan_sw = Klawisze
    Licznik_sw = 50
  End If
Return 

Ponieważ działanie jest takie samo jak w przypadku zwykłej klawiatury, nie będę omawiał szczegółowy wszystkich punktów procedury. Wartości zmiennej Klawisze są 16-bitowe podobnie jak Stan_sw. Działanie liczników jest analogiczne jak wyżej. Ponieważ procedura ta jest bardziej skomplikowana lepiej nie wykonywać jej co 4ms a np co 20ms. Z tak ustawionymi licznikami dało by to czas reakcji 120ms dla pierwszego kliknięcia i 1120ms dla ciągłego trzymania. Wywoływanie procedur klawiatury matrycowej powinno wyglądać tak:

   Gosub Matrycowka
   Gosub Przyciski




Portret użytkownika mareks6

Atmega8 + matrycówka 4x4 na dwóch portach

Witam, przymierzam się do budowy sterownika piły (długo by tu pisać) i planuję do tego wykorzystać klawiaturę matrycową. W projekcie chcę również użyć gotowego modułu wyświetlacza z układem TM1637 który jest sterowany tylko dwoma liniami mikroprocesora. Na przyszłość wolałbym sobie zostawić piny TxD oraz RxD nie używane, dlatego też podłączenie klawiatury matrycowej muszę rozdzielić na dwa porty - osobno kolumny i wiersze. Wydaje mi się że najlepszym rozwiązaniem w układzie ATmega8 będzie podłączenie jednego pod linie PD4-PD7, a drugiego pod linie PC0-PC3.

Czy ktoś już testował podobną konfigurację? Jak powinienem wtedy skonfigurować porty? Czy nie będzie z tym problemu? Testowałem już tę klawiaturę na jednym porcie - jak w przykładnie ale nigdy nie na dwóch, tak jak teraz to planuję zrobić.

Wolałbym wcześniej zapytać (zanim zaprojektuję PCB) czy ktoś już z tym miał problemy, bo jeśli tak to najwyżej zrobię klawiaturę na całym porcie D, a jak będę potrzebował port szeregowy to rozwiążę go programowo...

Portret użytkownika mirley

Trzeba tylko zmienić

Trzeba tylko zmienić procedure skanujaca klawiaturę....

Matrycowka:
  Klawisze = 0
  For Wiersz = 4 To 7
    Portd = Portd Or &B11110000
    Portd.Wiersz = 0
    Shift Klawisze , Left , 4
    Stan_Wiersz = Pinc And &B00001111
    Klawisze = Klawisze + Stan_Wiersz
  Next Wiersz
Return

pinc0-3 ma być wejściami z pullupem
pind4-7 to wyjścia

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.

Portret użytkownika mareks6

nie jestem teraz pewny, ale

nie jestem teraz pewny, ale jeśli się nie mylę to "Or" ustawia jedynki tylko tam gdzie w zapisie jest 1, a tam gdzie jest 0 - pozostawia stan taki jaki jest faktycznie na pinie? Analogicznie "And" ustawia 0 tam gdzie jest w zapisie 0, a tam gdzie jest 1 pozostawia stan taki jaki jest faktycznie?

Pytam gdyż zdążyłem już zapomnieć o podstawach tj maskowaniu, ale chyba tak to właśnie było?

Portret użytkownika mirley

Re: klawiatura

Dokładnie tak

-

UWAGA! Możliwy jest zakup zaprogramowanych uC i zestawów elementów itp. do niektórych projektów. O dostępność proszę pytać via email. Konkretne oferty pojawiają się w cenniku.