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.

ATmega32-problem z obsługą klawiatury

25 Kwi 2006 21:20 1188 2
  • Poziom 10  
    Witam wszystkich,

    Na wstępie od razu napiszę ,że czytałem już wiele na ten temat na avrfreaks i tutaj też ,jednak nie znalazłem odpowiedzi na swoje pytanie .Jeśli dubluję jakiś temat przepraszam ,ale uwierzcie że zadałem sobie troche trudu by poszukać w necie i samemu to rozwiązać. Piszę w C ,na darmowy kompilatorze winAVR ,mam zestawik z BTC .Testuje uproszczoną klawiaturkę 4 przyciskową .2 przyciski inkrementują liczbe wyświetlaną na ledach 2 pozostałe dekrementują .Wykorzystuje zewnętrzne przerwanie INT0 .
    Problem jest taki ,że na początku jest wszystko OK ,ale po jakis 30 wciśnięciach ,"zawiesza się" nie reaguje na ten przycisk ,na inny reaguje co 3 wciśnięcie ,po czym po kilku wciśnięciach znów reaguje na 3-4 wciśnięcia i znów 0 rekacji itd. Mam pojęcie o drganiach zestyków i o tym iż trzeba badac wiśnięcie i puszczenie .Robiłem opóźnienia na forze ,jak i na timerze 20ms aby to wyeliminowac -efekt taki sam .Może ktoś miał podobny problem i zechce podzielić się wskazówkami .Chodzi mi o idealne dopracowanie procedury obsługi klawiatury ,gdyż gdy będę zabierał się za coś trudniejszego będzie mi ona potrzebna i żebym sie nie zastanawiał czy może to ona moze źle działa. Chyba najlepiej żeby to opóźnienie było na forach ,bo timery będą mi potrzebne jeszcze w trudniejszych projektach .
    Dzięki z góry ,załączam kod:

    #include <avr\io.h>
    #include <avr\interrupt.h>

    #define OPOZNIENIE1 312

    typedef unsigned char byte; //8bitow 1B
    typedef unsigned short word; //16bitow 2B
    typedef unsigned long dword; //32 bity 4B

    byte liczba;
    volatile byte klawisz_wcisniety;
    dword i;

    void czekajT(void);
    void KonfigurujINT0(void);
    void WlaczPrzerwania(void);
    void WylaczPrzerwania(void);
    void KonfigurujTimer1(void);

    int main(void)
    {
    klawisz_wcisniety=0;
    liczba=0;

    DDRA = 0xFF; //PORT DIOD W TRYBIE WYJSCIOWYM
    DDRB &= 0xF0; //mlodsze 4 jako we
    PORTB |= 0x0F; //podciagane

    KonfigurujTimer1();
    WlaczPrzerwania();
    KonfigurujINT0();

    while(1)
    {
    PORTA = liczba;
    }

    return 0;
    }

    SIGNAL (INT0_vect)
    {
    czekajT();
    //for(i=0;i<30000;i++); //30 000 bylo juzniezle
    if(klawisz_wcisniety==0)
    {
    klawisz_wcisniety=1;
    if( (PINB&0x01)==0 )
    liczba++;
    else if( (PINB&0x02)==0 )
    liczba++;
    else if( (PINB&0x04)==0 )
    liczba--;
    else if( (PINB&0x08)==0 )
    liczba--;

    }
    else if(klawisz_wcisniety==1) //gdy wywola sie przerwanie i wcisn=1 to znaczy ze wlasnie
    klawisz_wcisniety=0; //zostal puszczony
    }

    void czekajT()
    {
    TIMSK |= 0x10; //wlacz przerwania od oc1a
    while( (TIFR&(0x10) ) ==0 ); //nie rob nic gdy flaga nie ustawiona
    //PORTA=128;
    TIFR &= 0xFE;//kasuje flage zapisujac zerem
    TIMSK &= 0xEF;//wylacz przerwania od oc1a
    }


    void KonfigurujINT0()
    {
    DDRD &= 0xFB; //ustaw PD2 - odp INT0 jako we
    PORTD |= 0x04; //portd (jako we) podciagaj

    // 7 6 5 4 3 2 1 0
    //SE SM2 SM1 SM0 ISC11 ISC10 ISC01 ISC00 MCUCR
    MCUCR |= 0x01; //dla zbocza opad isc01=1 ,isc00=0
    MCUCR &= 0xFD; //dla obu zbocz isc01=0 isc00=1

    //GIFR =0; //zeruj flagi przerwan
    // 7 6 5 4 3 2 1 0
    //INT1 INT0 INT2 – – – IVSEL IVCE GICR
    GICR |= 0x40; //INT0 enable
    }

    void WlaczPrzerwania()
    {
    sei();
    }

    void WylaczPrzerwania()
    {
    cli();
    }

    void KonfigurujTimer1()
    {
    //TCCR1B |= CS12 | CS10 | WGM12;
    TCCR1B|=0x0D;
    // 7 6 5 4 3 2 1 0
    //ICNC1 ICES1 – WGM13 WGM12 CS12 CS11 CS10
    //cs12=1 cs10=1 -dzielnik przez 1024
    //wgm12=1 ,wgm11=0,wgm10=0 wgm13=0 -tryb ctc porownuje z ocr1a
    TCCR1B&=0xEF; //WGM13=0

    TCCR1A&=0xFC;//WGM11=0 ,WGM10=0
    // 7 6 5 4 3 2 1 0
    //COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10

    //TCCR1B &= ~(WGM13);
    //TCCR1A &= ~(WGM11 | WGM10);

    OCR1A=OPOZNIENIE1;//zegar 16MHz 62,5ns -okres *1024 prescaler = 64us *312 =20ms

    //TIMSK|=0x10;//wlacz przerwania od oc1a
    // 7 6 5 4 3 2 1 0
    //OCIE2 TOIE2 TICIE1 OCIE1A OCIE1B TOIE1 OCIE0 TOIE0

    //TIMSK |= OCIE1A;
    //set_bits(TIMSK,0x10);
    }


    a tak zupełnie poza tematem przypomniała mi się 1 rzecz
    czemu wywala mi warning że "passing arg 1 of clear_bits ,making pointer from integer without a cast" i w rezultacie nie działa .Chodzi o funkcję clear_bits ,którą chciałem napisać dla ułatwienia sobie życia :
    static inline void clear_bits(volatile byte *p, byte mask)
    {
    *p &= ~mask;
    }
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • Pomocny post
    Poziom 35  
    Moim zdaniem masz żłe napisaną obsługe przerwania.
    Procesor jak wejdzie w przerwanie to w niej wisim i wisi.
    Mogą być problemy ze stosem.
    Ja bym to napisał tak ze timerem bym wykonywał akcje a w przerwaniu ustawiał flage wciśniętych klawiszy.
    Otrzymujesz przerwanie i zapisujesz do zmiennej stan klawiatury. W przerwaniu z Timera sprawdzasz jaki stan klawiszy jeśli wciśnięty to ustawiasz druga zmienną co by wyeliminowac drganie klawiszy. W kolejnym przerwaniu z timera sprawdzasz czy stan klawiszy był juz sprawdzany (czyt. eliminacja drgań) i jaki jest stan klawiatury jeśli taki sam jak był ustawiony przez przerwanie INT to robisz reakcje na dany klawisz.
  • Poziom 10  
    dzięki wielkie ,pomogło .Temat uważam za zamknięty.
    Pozdro!