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

Atmega 16, C Problem z INT0

Maciek4141 25 Lip 2009 22:50 1782 9
REKLAMA
  • #1 6821515
    Maciek4141
    Poziom 22  
    Witam!
    Chcę się przesiąść z Bascoma na C. Podstawy przerobiłem, teraz wziąłem się za przerwania. Najpierw chcę obsłużyć INT0, jednak za nic w świecie mi to nie wychodzi. Nóżkę INT0 (PIND2) mam podłączoną przez przycisk do masy.

    Czy możecie mi powiedzieć co jest źle w tym kodzie (fusy są odpowiednio skonfigurowane dla 8mhz)?

    #include <avr/io.h>
    #define F_CPU 8000000UL
    #include <avr/interrupt.h> 
    #define SETBIT(ADDRESS,BIT)   (ADDRESS |= (1<<BIT)) 
    #define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
    //
    
    
    SIGNAL(SIG_INTERRUPT0)
    {
    SETBIT(PORTB, 0);
    };
    
    
    int main(void)
    {
    DDRB=0xFF;
    
    CLEARBIT(MCUCR,ISC00);
    SETBIT(MCUCR,ISC01);
    GICR=(1<<INT0) ;
    
    sei();
    
    while(1)
    
    
    return 0;
    }
    
    


    Z góry dziękuję za pomoc
  • REKLAMA
  • #3 6821604
    Maciek4141
    Poziom 22  
    Ustawiłęm port jako wejście z podciągnięciem do + i nic to nie zmieniło.
    
    #include <avr/io.h>
    #define F_CPU 8000000UL
    #include <avr/interrupt.h> 
    #define SETBIT(ADDRESS,BIT)   (ADDRESS |= (1<<BIT)) 
    #define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
    //
    
    
    SIGNAL(SIG_INTERRUPT0)
    {
    SETBIT(PORTB, 0);
    };
    
    
    int main(void)
    {
    DDRB=0xFF;
    DDRD=0x00;
    PORTD=0xFF;
    
    CLEARBIT(MCUCR,ISC00);
    SETBIT(MCUCR,ISC01);
    GICR=(1<<INT0) ;
    
    sei();
    
    while(1)
    
    
    return 0;
    }
    
    


    W Bascomie obsługa działa bez problemu, może jednak źle zinterpretowałem opis rejestrów w datasheet?
  • REKLAMA
  • Pomocny post
    #4 6821701
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Po pierwsze:
    Teraz na topie są takie definicje przerwań ISR(INT0_vect) {...}

    Po drugie:
    while(1) 
    
    
    return 0;

    Po poprawnym sformatowaniu wygląda mniej więcej tak:
    while(1) 
    {
        return 0;
    }

    Chyba nie o to ci chodziło. Nie wiń C za swoje własne błedy.

    4\/3!!
  • #5 6822114
    Maciek4141
    Poziom 22  
    Wielkie dzięki, teraz działa.
    Możesz mi wytłumaczyć dlaczego return 0 musi być w tej nieskończonej pętli?
    Dlaczego jak umieszczę jakąś instrukcję w tej pętli nie jest ona wykonywana, dopiero dzieje się to kiedy dodam jeszcze jedną pętle przed w/w?
    Działa dopiero tak:
    sei(); 
    while(1)
    {
    SETBIT(PORTB, 1);
    _delay_ms(2000);
    CLEARBIT(PORTB,1);
    _delay_ms(2000);
    };
    
    while(1);
    { 
    
    
    return 0;
    
    };



    Przepraszam, może pytam o podstawy ale to nawyki z Bascoma i musze zmienić myślenie.
  • REKLAMA
  • Pomocny post
    #6 6822198
    snow
    Poziom 31  
    Może być tylko jedna pętla główna. Pierwsza pętla ci się zawsze wykonuje więc do drugiej nawet nie wchodzi. Co do returna to w petli jest niepotrzebny.
  • Pomocny post
    #7 6822256
    mirekk36
    Poziom 42  
    Maciek4141 --> przecież Freddie Chopin opisał ci jaki błąd robisz pisząc coś takiego:

    int main(void) 
    { 
    ....
    ....
    ....
    
    while(1) 
    
    return 0; 
    } 


    a ty to usprawniasz jeszcze "lepiej" - lepiej piszę w cudzysłowiu ;)


    while(1); 
    { 
    
    return 0; 
    
    };



    posłuchaj jeśli masz gołą funkcję main, czyli

    int main(void)
    {
    
    // jakaś tam inicjalizacja
    
      return 0;
    }


    to wpisujesz return 0; (to polecenie robi tak naprawdę właśnie nieskończoną pętlę - czyli w tym miejscu kończy się działanie programu.

    jeśli natomiast chcesz zastosować w main jakąś pętlę nieskończoną np:

    int main(void)
    {
    // jakaś inicjalizacja
    
      while (1)
      {
    
      }
    
      return 0;
    
    }



    to ten rozkaz return jest teoretycznie nie potrzebny, no chyba że jednak w ciele pętli while umieścisz gdzieś jakiś rozkaz break


    ty zrbiłeś w pierwszym listingu który pokazałeś wielkiego babola bo wpisałeś tak:

    while (1)
    return 0;


    a podejrzewam że chodziło ci o:

    while (1);
    return 0;


    widzisz ten średnik po while ????
    o nim zapomniałeś i przez to wyszła ci taka konstukcja którą rozwinął ci Freddie Chopin.

    a ty wpisałeś to do kodu:

    while(1)
    {
    
    return 0;
    }

    i dziwisz się że gdy w tej pętli coś chcesz zrobić to to się nie wykonuje no i nie dziwne

    teraz jaśniej?
  • REKLAMA
  • #8 6822495
    Maciek4141
    Poziom 22  
    No już jaśniej, wielkie dzięki. Dla mojej pełnej świadomości jeszcze chciałbym się upewnić.
    Napisałeś że
    Cytat:
    to wpisujesz return 0; (to polecenie robi tak naprawdę właśnie nieskończoną pętlę - czyli w tym miejscu kończy się działanie programu.

    Nie jestem pewien, czy dobrze rozumiem.
    Mam główną funkcję programu main, która zwracać musi wartość typu int.
    Jeżeli napiszę na koniec tej funkcji return 0 to funkcja main będzie wykonana tylko raz, bez żadnych powtórzeń?
    Jeżeli jednak chciałbym zastosować w programie jakieś powtarzające się czynności, wtedy muszę sam dołożyć drugą pętlę np while.


    Pozdrawiam
  • Pomocny post
    #9 6822553
    mirekk36
    Poziom 42  
    procedura main w C - to taka jakby główna pętla programu - z tym, że normalnie musi być w niej return 0; w warunkach o jakich pisałem wcześniej.

    Ta konstrukcja pełni wtedy hmmm podobną rolę jak byś w bascomie napisał główną pętlę:

    
    ' inicjalizacja portów
    ' inicjalizacja rejestrów
    ' odpalenie przerwań itp
    do
    loop

    Procedura main - nigdy nie jest powtarzana - a na jej wyjściu żaden wynik tej funkcji/procedury nigdzie nie jest zwracany bo to jest jakby jedna jedyna specyficzna główna procedura.

    Tak więc dokładnie tak jak piszesz - jeśli chcesz aby wewnątrz funkcji main coś działo się wiele razy to stosujesz odpowiednie pętle while lub for i podobne

    zwykle konstrukcja wygląda tak:

    int main(void)
    {
    
    .... tu jakaś inicjalizacja rejestrów
    .... przerwań itp
    .... odpalenie przerwań sei();
    
    -------------------------------------------
    
       ... tutaj właściwa część twojego programu i jeśli coś ma się wykonywać w pętli nieskończonej to dajesz właśnie np:
    
      while(1)
      {
          .... tu główny program
      }
    
    
      return 0;
    }
  • #10 6822564
    Maciek4141
    Poziom 22  
    Dziękuję serdecznie wszystkim, teraz już wszystko jasne.

    Pozdrawiam
REKLAMA