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

[Atmega32][C] obsługa klawiatury matrycowej w przerwaniu INT0 na płytce ZL3AVR

hexen2k 12 Mar 2011 18:01 4100 0
  • #1
    hexen2k
    Poziom 16  
    Wymyśliłem sobie, że będę obsługiwał klawiaturę matrycową 4x4 na płytce ZL3AVR w przerwaniu generowanym podczas naciśnięcia któregokolwiek klawisza (wyprowadzenie JP13 połączone mam z INT0), siedzę nad tym bardzo długo i nie mogę doszukać się swego myślowego błędu.

    Pierwszy wiersz (kolumna) działa poprawnie natomiast wszystkie pozostałe działają tak, że dopóki mam wciśnięty klawisz jest OK, a po jego zwolnieniu pokazuje się 0.


    Link



    Załączam wideo z nagraniem jak się to teraz zachowuje, kolumny z wierszami mam zamienione ale to mi nie przeszkadza, tak samo na filmiku widać, że pozostają drugie cyfry na wyświetlaczu (nie czyszczę go więc dlatego tak to wygląda ale to nie jest problemem):

    Code:

    #include <stdio.h>
    #include <avr/io.h>
    #include <hd44780.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>


    //ZMIENNE GLOBALNE i deklaracje funkcji//

    unsigned char czytaj_klawiature(void);
    char str[];
    volatile unsigned char klawisz; //klawisz jako char bez znaku


    //funkcja czytaj_klawiature//
    /*
        Funkcja czytaj_klawiature 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 czytaj_klawiature(void)
            {
                unsigned char wiersz,kolumna,key;
                for(kolumna=0xEF,key=1; kolumna>=0x71; (kolumna<<=1 | 0x01)&0xFF ) //3 wyrazenie for - przesun o 1 w lewo, wsun jedynke i zamaskuj całe 8 bitow
                    {
                        PORTA = kolumna;
                        for(wiersz=0x01; wiersz <= 0x08 ; wiersz<<=1, key++)
                            if(!(PINA & wiersz))
                            return key;

                    }
                return 0;
            }


    //obsluga klawiatury w przerwaniu  - zmiana stanu na pinie INT0//
    ISR(INT0_vect)
    {
        cli();
         klawisz = czytaj_klawiature();
         PORTA = 0x0F; //PA0...PA3 wejscia podciagniete, PA4...PA7 wyjscia stan niski (0) , trzeba przywolac pierwotny stan portu aby byl gotow na nastepne wywolanie przerwania
    }





    //KONFIGURACJA SPRZETU
    void init(void)
            {
                DDRD= 0x00; //PORTD wejściem
                PORTD = 0xFF; //PORTD podciagniety do VCC
                DDRA = 0xF0; //PA0...PA3 wejscia, PA4...PA7 wyjscia
                PORTA = 0x0F; //PA0...PA3 wejscia podciagniete, PA4...PA7 wyjscia stan niski (0)
                /* inicjalizuje wyswietlacz*/
                lcd_init();
                /* Wlacza wyswietlanie */
                LCD_DISPLAY(LCDDISPLAY);
                _delay_ms(200);
                /* Czysci  ekran */
                LCD_CLEAR;

                ////konfiguracja przerwania do obslugi klawiatury
                GICR |= (1<<INT0); //przerwanie INT0
                MCUCR |= (1<<ISC01); //aktywne zboczem opadajacym



            }



    //PROGRAM GLOWNY//

    int main(void)
    {
        init();



        while(1)
        {
            sei();
            LCD_LOCATE(0,0);
            sprintf(str,"%d",klawisz);
            lcd_puts(str);




        }



        ;

        return 0;
    }




    UPDATE:

    UWAGA ! tym razem korzystam z INT1 - zmiana wystąpiła na drodze licznych testów i prób (nie ma to żadnej różnicy w działaniu (porównując do INT0) oprócz tej że musiałem lekko zmienić kod programu)

    Po kilku kolejnych godzinach spędzonych nad układem doszedłem do pewnych spostrzeżeń:


    - Problemem w moim układzie są potworne zakłócenia które pojawiają się w momencie wciskania klawiszy z kolumny 2 3 i 4 (o dziwo na 1 kolumnie nie ma żadnych szpilek).
    - Po dołożeniu kondensatora 100n równolegle do wprowadzenia JP13 i VCC nie ma zakłóceń i układ działa prawidłowo (nie są to typowe drgania styków)
    - po umieszczeniu w przerwaniu dwóch linijek kodu które odpowiadają za podciąganie pinu INT1 do VCC:
    Code:

    //obsluga klawiatury w przerwaniu  - zmiana stanu na pinie INT0//
    ISR(INT1_vect)
    {
       PORTD = 0x00; //o te linijke chodzi
        klawisz = czytaj_klawiature();
        PORTA = 0x0F; //PA0...PA3 wejscia podciagniete, PA4...PA7 wyjscia stan niski (0) , trzeba przywolac pierwotny stan portu aby byl gotow na nastepne wywolanie przerwania
       PORTD = 0x08; //o te linijke chodzi
    }


    układ zaczyna działać prawie prawidłowo tzn. zakłócenia z kolumn 2 3 i 4 znikają, jednakże podczas obsługi przerwania pin INT1 "wisi w powietrzu" i prawdopodobnie przez to zamiast wciskanego klawisza czasem wskakuje 0 (dzieje się to juz rzadko)


    Załączam zmodyfikowany kod w którym zamienione są wiersze z kolumnami (przy wykorzystaniu matematycznego wzoru oraz dwóch zmiennych kn i wn odpowiednio dla kolumn i wierszy), oraz czyszczę wyświetlacz z poprzednich śmieci.

    Code:

    #include <stdio.h>
    #include <avr/io.h>
    #include <hd44780.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>


    //ZMIENNE GLOBALNE i deklaracje funkcji//

    unsigned char czytaj_klawiature(void);
    char str[];
    volatile unsigned char klawisz; //klawisz jako char bez znaku


    //funkcja czytaj_klawiature//
    /*
        Funkcja czytaj_klawiature 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 czytaj_klawiature(void)
            {
                unsigned char wiersz,kolumna,kn,wn;
                for(kolumna=0xEF,kn=1; kolumna<0xFF; kolumna=(kolumna<<1|0x01),kn++ ) //3 wyrazenie for - przesun o 1 w lewo, wsun jedynke i zamaskuj całe 8 bitow
                    {
                        PORTA = kolumna;
                        for(wiersz=0x01,wn=0; wiersz <= 0x08 ; wiersz<<=1, wn++)
                            if(!(PINA & wiersz)) return (kn+(wn*4));
                    }
                return 0;
            }


    //obsluga klawiatury w przerwaniu  - zmiana stanu na pinie INT0//
    ISR(INT1_vect)
    {
     //   PORTD = 0x00;
        klawisz = czytaj_klawiature();
        PORTA = 0x0F; //PA0...PA3 wejscia podciagniete, PA4...PA7 wyjscia stan niski (0) , trzeba przywolac pierwotny stan portu aby byl gotow na nastepne wywolanie przerwania
     //   PORTD = 0x08;
    }





    //KONFIGURACJA SPRZETU
    void init(void)
            {
                DDRD= 0x00; //PORTD wejściem
                PORTD = 0x08; //PORTD podciagniety do VCC
                DDRA = 0xF0; //PA0...PA3 wejscia, PA4...PA7 wyjscia
                PORTA = 0x0F; //PA0...PA3 wejscia podciagniete, PA4...PA7 wyjscia stan niski (0)
                /* inicjalizuje wyswietlacz*/
                lcd_init();
                /* Wlacza wyswietlanie */
                LCD_DISPLAY(LCDDISPLAY);
                _delay_ms(200);
                /* Czysci  ekran */
                LCD_CLEAR;

                ////konfiguracja przerwania do obslugi klawiatury
                GICR |= (1<<INT1); //przerwanie INT0
                MCUCR |= (1<<ISC11); //aktywne zboczem opadajacym



            }



    //PROGRAM GLOWNY//

    int main(void)
    {
        init();

        while(1)
        {
            sei();
            LCD_LOCATE(0,0);
            sprintf(str,"%d",klawisz);
            lcd_puts(str);
            _delay_ms(200);
            LCD_CLEAR;
        }

        ;

        return 0;
    }




    filmik który prezentuje obecne zachowanie układu:

    Link


    na początku działanie z podłączonym kondensatorem równolegle do INT1, potem odpinam kabelek z kondensatorem. Na oscyloskopie widać jakie zakłócenia są po wciśnięciu klawiszy kolumn 2 3 i 4 (na 1 kolumnie jest OK co widać też na oscyloskopie). Co ciekawe z kolumny 2 są najmniejsze a z 4 największe. Gdy INT1 jest niepodciągnięte do VCC na czas obsługi przerwania to zakłócenia te nie występują.

    Czy ktoś ma jakieś pomysły dlaczego to się tak dziwnie zachowuje ?
  • Tektronix