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.

[C] klawiatura matrycowa 4x4 - źle działający program

15 Maj 2010 12:03 3788 11
  • Poziom 9  
    Witam!

    Tak jak temacie, mam problem z programem do obsługi klawiatury matrycowej 4x4,
    Na stronie:
    Link
    Znalazłem kod:
    Code:

    #define F_CPU 1000000L
    #include <avr/io.h>
    #include <util/delay.h>

    /**** DEFINICJE WŁASNYCH FUNKCJI ****/

    /* Konfiguracja sprzętu */
    void init(void)
    {
       /* Konfiguruj portu A jako wyjścia */
       /* Wyświetlacz */
       DDRA  = 0xFF;
       PORTA = 0xFF;

       /* Klawiaturka  PD0..PD7 */
       DDRD  = 0x0f;
       PORTD = 0x7f;
    }

    /*
    Funkcja zmienia bajt w kodzie binarnym na bajt
    zakodowany w BCD
    */
    unsigned char bin2bcd(unsigned char bin)
    {
       if(bin>99) return bin;

       return  bin/10<<4 | bin%10;
    }

    /*
    Funkcja sprawdza kolejno wszystkie przyciski klawiatury
    i zwraca numer pierwszego wciśniętego przycisku, albo zero,
    gdy żaden przycisk nie został wciśnięty.
     */
    unsigned char read_keypad(void)
    {
       unsigned char row,col,key;
       
       for(row=0x7e,key=1; row>=0x77; row=(row<<1|0x1)&0x7f)
       {
            PORTD = row;
          for(col=0x10; col< 0x80; col<<=1, key++)
                       if(!(PIND & col)) return key;
       }
       return 0;
    }

    /**** POCZĄTEK PROGRAMU ****/

    /* Definicja funkcji main */
    int main(void)
    {
       unsigned char key;

    /* Konfiguracja portów we/wy */
       init();

    /* Nieskończona pętla */
       for(;;)
          if(key = read_keypad())
                 PORTA = bin2bcd(key);
    }


    Problem polega na tym, że jest to program do obsługi klawiatury 4x3.
    Pomimo wielu prób, nie udało mi się go tak zmodyfikować, żeby działał dla klawiatury 4x4.
    Bardzo proszę o pomoc!

    Pozdrawiam!
  • Pomocny post
    Poziom 20  
    ten for w funkcji read_keypad:
    Code:
          for(col=0x10; col< 0x80; col<<=1, key++) 
    
                       if(!(PIND & col)) return key;

    sprawdza Ci tylko 3 kolumny wiec musisz przerobic zeby wszystkie cztery lecial...
    np.
    Code:
          for(col=0x10; col; col<<=1, key++) 
  • Poziom 9  
    Masz rację, działa, dziękuje. Ja wcześniej sprawdzałem:
    Code:

    for(col=0x10; col<=0x80; col<<=1, key++

    ale nie zadziałało prawidłowo.

    Niestety zauważyłem, że czasami trzeba przytrzymać przycisk dłużej aby zadziałał prawidłowo, podejrzewam że trzeba gdzieś dodać.
    Code:
    delay();
  • Pomocny post
    Poziom 38  
    Zapewne przed ifem sprawdzającym stan portu. jeden nop powinien wystarczyć
  • Poziom 9  
    Zgadza się, wrzuciłem:
    Code:

    for(col=0x10; col; col<<=1, key++)
    {
       _delay_ms(20);
            if(!(PIND & col)) return key;
    }

    i działa lepiej.

    Dziękuję za pomoc!
  • Poziom 20  
    a jak myslisz, czemu Ci nie dzialalo w ten sposob?
    Code:
    for(col=0x10; col<=0x80; col<<=1, key++


    przeanalizuj, a wiecej takich kwiatkow nie popelnisz :)
  • Poziom 38  
    nie 20ms tylko nop! dlatego, że za szybko odczytujesz stan portu po jego ustawieniu.
  • Poziom 9  
    Zastosowałem:
    Code:

    for(col=0x10; col; col<<=1, key++)
    {
          asm("nop");
          if(!(PIND & col)) return key;
    }


    ale wg mnie lepiej działało z:

    Code:

    for(col=0x10; col; col<<=1, key++)
    {
            _delay_ms(20);
            if(!(PIND & col)) return key;
    }


    @H0miczek: key jeszcze raz sie musi zinkrementowac?
  • Pomocny post
    Poziom 38  
    col<<=1 o to mu zapewne chodzi.

    nop wystarczy a większe opóźnienie jak już daj w innym miejscu.
    Ja te klawiatury obsługuje w przerwaniu, więc to inna historia
  • Poziom 9  
    Ok, w takim razie gdzie lepiej dać takie większe opóźnienie?
    Po instrukcji if?

    P.S. mógłbyś wrzucić kod jak Ty rozwiązałeś to na przerwaniach?
  • Pomocny post
    Poziom 38  
    Obsługa klawki 4x4
    Code:
    void KBD_init(void)
    
    {
    KBD_DIR = 1<<KBD_col1 | 1<<KBD_col2 | 1<<KBD_col3 | 1<<KBD_col4 |
    ~(1<<KBD_row1 | 1<<KBD_row2 | 1<<KBD_row3 | 1<<KBD_row4);

    KBD_PORT = 0xFF;
    };

    unsigned char KBD_read(void)
    {
    KBD_PORT=0xff;
    KBD_PORT &= ~(1<<KBD_col1);

    asm volatile("nop");
    asm volatile("nop");

       if( !(KBD_PIN & (1<<KBD_row1)))
          return (1);
       if( !(KBD_PIN & (1<<KBD_row2)))
          return (2);   
       if( !(KBD_PIN & (1<<KBD_row3)))
          return (3);
       if( !(KBD_PIN & (1<<KBD_row4)))
          return (KEY_A);

    KBD_PORT |=  (1<<KBD_col1);
    KBD_PORT &= ~(1<<KBD_col2);

    asm volatile("nop");
    asm volatile("nop");

       if( !(KBD_PIN & (1<<KBD_row1)))
          return (4);
       if( !(KBD_PIN & (1<<KBD_row2)))
          return (5);   
       if( !(KBD_PIN & (1<<KBD_row3)))
          return (6);
       if( !(KBD_PIN & (1<<KBD_row4)))
          return (KEY_B);
     
    KBD_PORT |=  (1<<KBD_col2);
    KBD_PORT &= ~(1<<KBD_col3);

    asm volatile("nop");
    asm volatile("nop");

       if( !(KBD_PIN & (1<<KBD_row1)))
          return (7);
       if( !(KBD_PIN & (1<<KBD_row2)))
          return (8);   
       if( !(KBD_PIN & (1<<KBD_row3)))
          return (9);
       if( !(KBD_PIN & (1<<KBD_row4)))
          return (KEY_C);

    KBD_PORT |=  (1<<KBD_col3);
    KBD_PORT &= ~(1<<KBD_col4);

    asm volatile("nop");
    asm volatile("nop");

       if( !(KBD_PIN & (1<<KBD_row1)))
          return (KEY_GW);
       if( !(KBD_PIN & (1<<KBD_row2)))
          return (0);   
       if( !(KBD_PIN & (1<<KBD_row3)))
          return (KEY_KR);
       if( !(KBD_PIN & (1<<KBD_row4)))
          return (KEY_D);

    KBD_PORT |=  (1<<KBD_col4);
    return (0xFF);
    }


    definy

    Code:
    // linie kolumn klawiatury
    
    #define KBD_PORT   PORTB
    #define KBD_DIR      DDRB
    #define KBD_PIN      PINB

    #define KBD_col1   7

    #define KBD_col2   6

    #define KBD_col3   5

    #define KBD_col4   4

    // linie wierszy klawiatury

    #define KBD_row1   3

    #define KBD_row2   2

    #define KBD_row3   1

    #define KBD_row4   0


    funkcje odczytu wrzucam w przerwanie przepełnienia t0 które mam co około 40ms
    Tam dodatkowo możesz rozwiązać przytrzymanie klawisza i inne pierdoły, dzieki temu odrazu eliminujesz drgana stykow
  • Poziom 9  
    Wielkie Dzięki!