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

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

HonestStanley 15 Maj 2010 12:03 3977 11
REKLAMA
  • #1 8077804
    HonestStanley
    Poziom 10  
    Witam!

    Tak jak temacie, mam problem z programem do obsługi klawiatury matrycowej 4x4,
    Na stronie:
    Link
    Znalazłem kod:
    
    #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!
  • REKLAMA
  • Pomocny post
    #2 8077855
    H0miczek
    Poziom 20  
    ten for w funkcji read_keypad:
          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.
          for(col=0x10; col; col<<=1, key++) 
  • REKLAMA
  • #3 8078065
    HonestStanley
    Poziom 10  
    Masz rację, działa, dziękuje. Ja wcześniej sprawdzałem:
    
    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ć.
  • Pomocny post
    #4 8078074
    tadzik85
    Poziom 38  
    Zapewne przed ifem sprawdzającym stan portu. jeden nop powinien wystarczyć
  • REKLAMA
  • #5 8078141
    HonestStanley
    Poziom 10  
    Zgadza się, wrzuciłem:
    
    for(col=0x10; col; col<<=1, key++)
    {
    	_delay_ms(20);
            if(!(PIND & col)) return key;
    }
    

    i działa lepiej.

    Dziękuję za pomoc!
  • #7 8078243
    tadzik85
    Poziom 38  
    nie 20ms tylko nop! dlatego, że za szybko odczytujesz stan portu po jego ustawieniu.
  • REKLAMA
  • #8 8078543
    HonestStanley
    Poziom 10  
    Zastosowałem:
    
    for(col=0x10; col; col<<=1, key++)
    {
    		asm("nop"); 
          if(!(PIND & col)) return key; 
    }
    


    ale wg mnie lepiej działało z:

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


    @H0miczek: key jeszcze raz sie musi zinkrementowac?
  • Pomocny post
    #9 8078598
    tadzik85
    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
  • #10 8078806
    HonestStanley
    Poziom 10  
    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
    #11 8078817
    tadzik85
    Poziom 38  
    Obsługa klawki 4x4
    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

    // 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
  • #12 8079142
    HonestStanley
    Poziom 10  
    Wielkie Dzięki!
REKLAMA