Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Klawiatura matrycowa 2x2 - problem

14 Kwi 2010 21:46 1801 4
  • Poziom 10  
    Witam

    Mam taki dziwny problem. Dla potrzeb budowy zegara (4 klawisze) wymyśliłem sobie, że klawiatura zostanie zrealizowana jako matryca o rozmiarze 2x2.
    Po napisaniu oprogramowania aby zobaczyć czy to w ogóle działa użyłem zestawu ZL3AVR (nie będę się tu o nim rozpisywał bo nie w tym rzecz). No i wszystko ładnie, pięknie. Program mający jedynie wyświetlać numer klawisza po jego wciśnięciu działa bez zarzutu. Natomiast po podłączeniu pod owy zestaw panelu przedniego budowanego urządzenia (obudowa metalowa, przyciski, a raczej takie większe guziki, połączone kabelkami) niby wszytko też działa ALE co kilka naciśnięć (nie za każdym razem) da się zauważyć, że mylone są kolumny klawiatury. Wiersze działają bez zarzutu. Przyznam szczerze skończyły się się pomysły co może być nie tak.
    Oprogramowanie - nie działałoby na samym zestawie symulacyjnym, a działa.
    Połączenie - no niby ok skoro mimo wszytko przeważnie wyświetla dobry numer klawisza.
    Tak więc co tu może być nie halo? POMOCY.
  • Poziom 38  
    A ja się zastanawiam na sensem tego rozwiązania. Wykorzystujesz tyle samo pinów procesora, gdybyż każdy przycisk podłączył do osobnego pinu. Łatwiej oprogramować. A przyczyn może być wiele. Za szybko sprawdzasz przyciski, drgania styków. Brak włączonego podciągania. Ja swego czasu głowiłem się dlaczego nie działa mi jeden wiersz, okazało się, że za szybko sprawdzam stan pinu.

    Ale, żeby myliło kolumny? Interesujący problem.
  • Poziom 24  
    l_taras napisał:
    Dla potrzeb budowy zegara (4 klawisze) wymyśliłem sobie, że klawiatura zostanie zrealizowana jako matryca o rozmiarze 2x2.


    Dobre! A ile linii zaoszczędziłeś :-)

    l_taras napisał:
    niby wszytko też działa ALE co kilka naciśnięć (nie za każdym razem) da się zauważyć, że mylone są kolumny klawiatury.


    Szklana kula jest w naprawie. Pokaż schemat i program. Tak na ślepo, to można powiedzieć, że dałeś zbyt krótkie opóźnienia między wymuszeniem stanu kolumny a odczytem stanu wiersza.
  • Moderator Mikrokontrolery Projektowanie
    Też obstawiam za krótkie opóżnienia, ew. ustawianie wartości IO i natychmiastowe odczytanie - AVR muszą mieć NOPa, żeby zsynchronizować latcha na pinie pracującym jako wejście.
    BTW, jak koledzy napisali pomysł z matrycą w tym przypadku jakoś marnie wyszedł :) To można zrobić na jednym pinie ADC - przyciski zwierają rezystory na drabince R2R robiącej jako dzielnik. Zaleta oprócz tego, że masz tylko jeden pin IO zajety to to, że masz poprawną obsługę wciśnięcia kilku przycisków na raz, co na matrycy wymaga dodatkowych diod. No i można wykorzystać przerwanie komparatora do sygnalizacji, ze użytkownik coś wcisnął.
  • Poziom 10  
    Cytat:
    Pokaż schemat i program


    Oto schemat:
    Klawiatura matrycowa 2x2 - problem
    Na nim bazowałem.

    Oto program główny:
    Code:
    #define F_CPU 1000000UL
    
    #include <avr/io.h>
    #include <inttypes.h>
    #include <util/delay.h>

    #include <LCD.c>
    #include <Klawiatura_2x2.c>

    unsigned char    klawisz; //ostatnio  naciśniety klawisz

    //-----------------------------------------------------------------------------------------------------------------------------------------------

    void key_1()
    {
       czysc_lcd();
       zapis_tekstu("1");
    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------


    //-----------------------------------------------------------------------------------------------------------------------------------------------

    void key_2()
    {
       czysc_lcd();
       zapis_tekstu("2");
    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------


    //-----------------------------------------------------------------------------------------------------------------------------------------------

    void key_3()
    {
       czysc_lcd();
       zapis_tekstu("3");
    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------



    //-----------------------------------------------------------------------------------------------------------------------------------------------

    void key_4()
    {
       czysc_lcd();
       zapis_tekstu("4");;
    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------


    int main(void)
    {
       KBD_init();   //inicjowanie klawiatury
       inicjalizacja_lcd();
          
       while(1)
       {
          if (KBD_read()) //jeżeli nacisniety jakis klawisz
          {      
             klawisz=KBD_key; //zapamietanie jaki klawisz zostal nacisniety
             KBD_wait();   //odczekanie aż klawisz zostanie puszczony

             switch(klawisz) //wybór reakcji w zależnosci od naciśniętego klawisza
             {   
             case 1: key_1();
             break;
             
             case 2: key_2();
             break;
             
             case 3: key_3();
             break;
             
             case 4: key_4();
             break;
             }
          }
       }
       return(0);
    }


    I biblioteki:
    - plik c
    Code:


    #include "Klawiatura_2x2.h"


    //-----------------------------------------------------------------------------------------------------------------------------------------------
    //Inicjacja klawiatury
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    void KBD_init(void)
    {
       // ustawienie kolumn na zapis
       sbi(KBD_PORT_D_col1,KBD_BIT_col1); 
       sbi(KBD_PORT_D_col2,KBD_BIT_col2);
    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------


    //-----------------------------------------------------------------------------------------------------------------------------------------------
    //Oczekiwanie na puszczenie klawisza
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    void KBD_wait(void)
    {
      while(KBD_read()>0);
      _delay_ms(20);

    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------


    //-----------------------------------------------------------------------------------------------------------------------------------------------
    //Funkcja czyta klawiature i zwraca kod naciśnietego klawisza (jeśli nic nie naciśnięto funkcja zwraca 0)
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    unsigned char KBD_key; //zmienna przechowująca kod ostatnio przyciśniętego klawisza

    unsigned char _KBD_readcol(unsigned char col) //funkcja pomocnicza (odczyt kolumny)
    {
       register unsigned char c=0;
       if (KBD_row1) c=col; else
       if (KBD_row2) c=col+1;
       return(c);
    }

    unsigned char KBD_read(void) //odczyt klawiatury
    {
      register unsigned char k;
       //ustawienie rzędów na odczyt
       cbi(KBD_PORT_D_row1,KBD_BIT_row1); 
       cbi(KBD_PORT_D_row2,KBD_BIT_row2);

       //załączenie rezystorów podciągających na liniach rzędów
       sbi(KBD_PORT_row1,KBD_BIT_row1);
       sbi(KBD_PORT_row2,KBD_BIT_row2);

       KBD_key=0;
       KBD_col1_0;
       k=_KBD_readcol(1);
       
       if (k>0)
          KBD_key=k;
       
       KBD_col1_1;
       KBD_col2_0;
       k=_KBD_readcol(2);
       
       if (k>0)
          KBD_key=1+k;

       return(KBD_key);
    }
    //-----------------------------------------------------------------------------------------------------------------------------------------------


    - plik h
    Code:

    #include <avr/io.h>

    //#include "global.h"

    // linie kolumn klawiatury
    #define KBD_PORT_col1   PORTC
    #define KBD_BIT_col1   7
    #define KBD_PORT_col2   PORTC
    #define KBD_BIT_col2   6

    // linie wierszy klawiatury
    #define KBD_PORT_row1   PORTC
    #define KBD_BIT_row1   5
    #define KBD_PORT_row2   PORTC
    #define KBD_BIT_row2   4


    #define KBD_PORT_D_col1 DDR(KBD_PORT_col1)
    #define KBD_PORT_D_col2 DDR(KBD_PORT_col2)

    #define KBD_PORT_I_col1 PIN(KBD_PORT_col1)
    #define KBD_PORT_I_col2 PIN(KBD_PORT_col2)

    #define KBD_PORT_D_row1 DDR(KBD_PORT_row1)
    #define KBD_PORT_D_row2 DDR(KBD_PORT_row2)

    #define KBD_PORT_I_row1 PIN(KBD_PORT_row1)
    #define KBD_PORT_I_row2 PIN(KBD_PORT_row2)

    #define KBD_row1   bit_is_clear(KBD_PORT_I_row1,KBD_BIT_row1)
    #define KBD_row2   bit_is_clear(KBD_PORT_I_row2,KBD_BIT_row2)

    #define KBD_col1_0   cbi(KBD_PORT_col1,KBD_BIT_col1)
    #define KBD_col2_0   cbi(KBD_PORT_col2,KBD_BIT_col2)

    #define KBD_col1_1   sbi(KBD_PORT_col1,KBD_BIT_col1)
    #define KBD_col2_1   sbi(KBD_PORT_col2,KBD_BIT_col2)

    #define DDR(x) (_SFR_IO8(_SFR_IO_ADDR(x)-1))
    #define PIN(x) (_SFR_IO8(_SFR_IO_ADDR(x)-2))

    #define cbi(PORT, BIT) (_SFR_BYTE(PORT) &= ~_BV(BIT))
    #define sbi(PORT, BIT) (_SFR_BYTE(PORT) |= _BV(BIT))

    #define KBD_pressed()   KBD_read()>0 //makro sprawdzająca czy klawiatura jest naciśnięta

    extern unsigned char KBD_key; //zmienna przechowująca kod ostatnio przyciśniętego klawisza


    //-----------------------------------------------------------------------------------------------------------------------------------------------
    //Deklaracje funkcji
    //-----------------------------------------------------------------------------------------------------------------------------------------------
    void KBD_init(void); //inicjacja klawiatury
    unsigned char KBD_read(void); //funkcja czyta klawiature i zwraca kod naciśnietego klawisza (jeśli nic nie naciśnięto funkcja zwraca 0)
    void KBD_wait(void); //oczekiwanie na puszczenie klawisza
    //-----------------------------------------------------------------------------------------------------------------------------------------------


    tmf - Nie mam dużego doświadczenia z AVR-ami. 1 czy 4 piny przy Medze32 to raczej niewielkie ma znaczenie. Dzięki za pomysł ale musiałbym dodatkowo ogarniać przetwornik. Wystarczy mi póki co do ogarnięcia to co mam :)