logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATmega32][C/AVR-GCC] obsługa przycisków

amarthwen 06 Maj 2011 01:53 3415 2
REKLAMA
  • #1 9475687
    amarthwen
    Poziom 2  
    Witam wszystkich użytkowników!
    Jest to mój pierwszy post na forum elektroda.pl mam więc nadzieję, że okażecie mi trochę zrozumienia i pomożecie odpowiedzieć na pytanie, które już nie raz zdążyło pojawić się na tym forum. Przeszukałem dokładnie każdy temat dotyczący obsługi przycisków pod ATmegą8, ATmegą16 czy ATmegą32 jednak w żadnym z nich nie znalazłem instrukcji, która krok po kroku wyjaśniłaby schemat działania tej prostej klawiatury. Mikrokontrolerami AVR zajmuję się od niedawna (spokojnie można powiedzieć, że jestem na etapie początkującym) tak więc pisząc program obsługi przycisków pojawiło się w mojej głowie pytanie, które kieruję do Was, a które brzmi następująco: czy kod i opis obsługi przycisków opisany przeze mnie poniżej jest w 100% prawidłowy? jeżeli tak to mógłby posłużyć osobom, które podobnie jak ja zaczynają "przygodę" z programowaniem mikrokontrolerów AVR, a które nie miały do tej pory większego pojęcia o tym jak to wszystko działa.

    Posiadam zestaw uruchomieniowy ZL3AVR. Piny kolumn K1, K2, K3 i K4 klawiatury łączę kablami odpowiednio z pinami PC0, PC1, PC2 i PC3 portu C mikroprocesora. Piny wierszy W1, W2, W3 i W4 klawiatury łączę kablami odpowiednio z pinami PC4, PC5, PC6 i PC7 portu C mikroprocesora. Piny portu A mikroprocesora łączę analogiczne kablami z pinami panelu LED (piny od D0 do D7).

    kod programu:
    
    #define F_CPU 8000000L //wewnętrzny kwarc Atmegi32 taktowany 8MHz, w zewnętrznym kwarcu powinno być 16000000L (16MHz)
    #include <avr/io.h>
    #include <stdint.h>
    #include <util/delay.h>
    
    uint8_t ScanKeyboard(){
      for(uint8_t i = 0; i < 4; ++i){
        PORTC = ~(1 << i); //aktywuj i-tą kolumnę stanem niskim
        for(uint8_t j = 0; j < 4; ++j) if(!((PINC >> (4 + j)) & 1)) return 4 * j + i; //jeżeli w j-tym wierszu pojawi się stan niski to mamy szukany przycisk (i-ta kolumna, j-ty wiersz), zwróć kod przycisku
      }
      return 0x10; //jeżeli nie został wciśnięty żaden przycisk - zwróć kod przycisku 0x10 (który nie istnieje)
    }
    
    int main(){
      DDRA = 0xff; //PORTA jako wyjście dla diod led (panel LED, piny od D0 do D7)
      PORTA = 0x00;
      DDRC = 0x0f; //4 młodsze bity PORTC jako wyjście, 4 starsze jako wejście z pull-upami
      PORTC = 0xf0;
      while(1){
        if(~(PINC >> 4) & 0x0f){ 
          _delay_ms(20);
          if(~(PINC >> 4) & 0x0f){
            PORTA = ScanKeyboard();
            PORTC = 0xf0;
            while(~(PINC >> 4) & 0x0f);
          }
        } 
      }    
    }
    

    konfiguracja portów:
    Na początku funkcji main() PORTA ustawiam jako wyjście dla diod led (które będę wyświetlały binarną reprezentację kodu wciśniętego przycisku). Kod przycisku S1 jest równy 0 a idąc "w prawo" kody kolejnych przycisków są większe od poprzednich o 1, tj. kod przycisku S2 = 1, S3 = 2, S4 = 3, S5 = 4 itd. 4 młodsze bity PORTC ustawiam jako wyjście (PC0 jako pin wejściowy K1 klawiatury, PC1 jako pin wejściowy K2 klawiatury itd.). 4 starsze bity PORTC ustawiam jako wejście z pull-upami (PC4 jako pin wyjściowy W1 klawiatury, PC5 jako pin wyjściowy W2 klawiatury itd.).

    działanie programu:
    piny wejściowe klawiatury K1 do K4 zeruję
    PORTC = 0xf0;

    oznacza to, że wszystkie cztery kolumny przycisków są teraz aktywne bowiem i-tą kolumnę aktywujemy stanem niskim, tj. na i-tym bicie PORTC ustawiamy wartość 0. Jeżeli na i-tym bicie jest ustawiona wartość 1 to oznacza, że i-ta kolumna jest nieaktywna. Następna instrukcja warunkowa
    if(~(PINC >> 4) & 0x0f){

    sprawdza czy na którymkolwiek z czterech wierszy (bity PC4 do PC7) pojawił się stan niski, jeżeli tak to oznacza, że został wciśnięty przycisk (jeżeli wszystkie cztery bity PC4 do PC7 mają wartość 1 tzn, że nie został wciśnięty żaden przycisk). Program czeka 20ms w celu wyeliminowania efektu drgania styków po czym ponownie sprawdza czy został wciśnięty którykolwiek z przycisków. Następnie na PORTA zostaje wysłana binarna reprezentacja kodu przycisku
    PORTA = ScanKeyboard();

    funkcja ScanKeyboard() po kolei aktywuje każdą z czterech kolumn klawiatury za każdym krokiem sprawdzając czy na którymś z wierszy pojawił się stan niski (wtedy mamy szukany przycisk (i-ta kolumna, j-ty wiersz) i jego kod = 4 * j + i). Po wykonaniu funkcji ScanKeyboard() zostają aktywowane wszystkie cztery kolumny klawiatury i program czeka na zwolnienie przytrzymanego przycisku.
    PORTC = 0xf0;
    while(~(PINC >> 4) & 0x0f);

    będę wdzięczny za wszystkie uwagi dotyczące poprawności i opisu działania kodu oraz wszelkie jego usprawnienia, pozdrawiam!
  • REKLAMA
  • Pomocny post
    #2 9476036
    Andrzej__S
    Poziom 28  
    Cytat:

    Przeszukałem dokładnie każdy temat dotyczący obsługi przycisków pod ATmegą8, ATmegą16 czy ATmegą32 jednak w żadnym z nich nie znalazłem instrukcji, która krok po kroku wyjaśniłaby schemat działania tej prostej klawiatury.
    ....
    Piny kolumn K1, K2, K3 i K4 klawiatury łączę kablami odpowiednio z pinami PC0, PC1, PC2 i PC3 portu C mikroprocesora. Piny wierszy W1, W2, W3 i W4 klawiatury łączę kablami odpowiednio z pinami PC4, PC5, PC6 i PC7 portu C mikroprocesora.

    Chyba nie szukałeś zbyt dokładnie, albo niezbyt dobrze zrozumiałeś to co znalazłeś. Przy takim sterowaniu klawiaturą powinieneś mieć klawiaturę podłączoną przez diody, lub przy takim podłączeniu klawiatury powinieneś zmienić algorytm sterowania. Zabezpieczy to mikrokontroler przed zbyt dużymi prądami obciążającymi wyjścia portu C w przypadku jednoczesnego naciśnięcia dwóch lub więcej klawiszy. Bliższych szczegółów dowiesz się może stąd.
  • #3 9476193
    amarthwen
    Poziom 2  
    Dziękuję za link, na tą stronę nie trafiłem (a starałem się szukać dokładnie by nie powielać tego samego wątku). Rozumiem, że zmiana algorytmu skanowania na ten, który opisał arturt134 powinna rozwiązać problem dużych prądów obciążających wyjścia portu C w przypadku jednoczesnego naciśnięcia dwóch lub więcej klawiszy.
REKLAMA