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.

Problem z zewnętrznym przerwaniem

31 Gru 2010 19:38 1020 3
  • Poziom 13  
    Witam.

    Podłączyłem klawiaturę do uc, naciśniecie przycisku powoduje zmianę stanu wejścia PD2 przez co uc wskakuje w przerwanie. W nim sprawdza po kolei który dokładnie przycisk jest wciśnięty poprzez podłączenie wyjść switchy do GND co ma spowodować spadek napięcia na PD2 czyli logiczne 0. W przerwanie dobrze wykrywa który przycisk jest wciśnięty, sygnalizuje to ilość zapalonych diod podłączonych pod PA. Następnie czeka na puszczenie przycisku i 10ms aby wyeliminować drganie styków i ponowne wejście w przerwanie. Po odczekaniu 10ms nie wiem czemu ale na porcie A ustawiana jest jakaś dziwna wartość tj. 0b11111110 nie mam pojęcia czemu się tak dzieje.

    Code:
    #include <avr/io.h>
    
    #include <util/delay.h>
    #include <avr/interrupt.h>

    #define SetBit(x,y)   x |= (1<<y)
    #define ClrBit(x,y) x &= ~(1<<y)
    #define NegBit(x,y) x ^= (1<<y)

    volatile int p=0;

    ISR (INT0_vect)
    {
          _delay_ms(5);
          p=0;

          NegBit(PORTA, 4);

          ClrBit(DDRD, 7);
             _delay_ms(5);
             if(bit_is_set(PIND, 2)) p=4;
          SetBit(DDRD, 7);
             _delay_ms(5);


          ClrBit(DDRD, 6);
             _delay_ms(5);
             if(bit_is_set(PIND, 2)) p=3;
          SetBit(DDRD, 6);
             _delay_ms(5);


          ClrBit(DDRD, 5);
             _delay_ms(5);
             if(bit_is_set(PIND, 2)) p=2;
          SetBit(DDRD, 5);
             _delay_ms(5);


          ClrBit(DDRD, 4);
             _delay_ms(5);
             if(bit_is_set(PIND, 2)) p=1;
          SetBit(DDRD, 4);
             _delay_ms(5);

          DDRD=0b11110000;


          if(p==1)
          {
             PORTA=0b01111111;
             p=0;
          }

          if(p==2)
          {
             PORTA=0b00111111;
             p=0;
          }

          if(p==3)
          {
             PORTA=0b00011111;
             p=0;
          }

          if(p==4)
          {
             PORTA=0b00001111;
             p=0;
          }


          while(bit_is_clear(PIND, 2))
          {
             NegBit(PORTA, 3);
             _delay_ms(100);
          }

          _delay_ms(20);
    }


    int main(void)
    {
       DDRD=0xf0;
       PORTD=0b00001100;
       DDRA=0xff;
       PORTA=0b01010101;

       // Przyciski//
       MCUCR = (1<<ISC01);
       GIMSK |= (1<<INT0);

       sei();

       while(1)
       {

       }
    }


    Schemat wygląda mniej więcej tak z tym, że klawiatura podłączona jest pod inne WE/WY.

    Problem z zewnętrznym przerwaniem
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • Poziom 42  
    Witam,

    Niestety ale strasznie źle podchodzisz do tego zagadnienia bo w przerwaniu dajesz jakieś masakryczne opóźnienia i pętle, które mogą się nie skończyć nigdy. Zdecydowanie odradzam takie pomysły.

    Przerwania dla klawiatury matrycowej, owszem można używać ale postaraj się skorzystać z flag i te sprawdzania, które tu wykonujesz w przerwaniu przenieś do pętli głównej to od razu będzie lepszy efekt - jeśli chodzi o takie testy oczywiście. Bo generalnie to i tak tego typu obsługa będzie blokująca z uwagi na te wszystkie _delay'e.
  • Poziom 23  
    Poco delay w przerwaniu :?: Nie lepiej pomanipulować preskalerem :?:
    A te wszystkie przyciski to po prostu przed diodę i na wejście przerwania :)
    Kliknięcie któregokolwiek z przycisków spowoduje wejście w przerwania a tam prosty chociażby switch + volatile załatwi sprawę rozpoznania przycisku (pinu)

    Pozdrawiam maly_elektronik
  • Poziom 27  
    Czemu ty robisz tam taką konstrukcję:

    Code:
    ClrBit(DDRD, 4); 
    
             _delay_ms(5);
             if(bit_is_set(PIND, 2)) p=1;
          SetBit(DDRD, 4);


    Mylisz rejestry - powinieneś zmieniać stan rejestrów PORT a nie DDR.
    DDR ustaw na zawsze jako wyjściowe.