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

[ATmga128][C] Nieobliczane przerwanie od timera 0

nelik1987 08 Gru 2009 14:11 1434 5
  • #1 08 Gru 2009 14:11
    nelik1987

    Poziom 31  

    Witam męczę się już od dawna z przerwaniem od timera 0. Wymyśliłem sobie że po przepełnieniu licznika 0 ma nastąpić przerwanie. Licznik 0 liczy od 0-255 chciałem miec kontrolę na częstotliwością wywoływania przerwania więc gdy przerwanie jest wykonywane wpisuję od razu do licznika konkretną liczbę tak by miał on mniej do zliczania. Problem polega na tym ze przerwanie zawsze wykonuje się w jednym określonym czasie niezależnie od tego co wpiszę do licznika jako wartość początkową.

    kod programy:

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

    ///// LEDY //////
    #define LED_ON PORTC |= _BV(0);
    #define LED_OFF PORTC &= ~_BV(0);
    #define LED_TOGGLE PORTC ^= _BV(0);


    ISR (TIMER0_OVF_vect)
    {
        LED_TOGGLE;
        TCNT0 = 198;                // Załaduj wartość początkową do timera 0
        overflow1++;
        overflow2++;
        overflow3++;
        overflow_ADC++;   
    }


    int main (void)
    {

    DDRC = 255; // Ustawienie rejestru C jako TEST

    TIMSK = _BV(TOIE0);        // włącz obsługę przerwań od timera 0

    TCCR0  |= (1 << CS00);         //Ustawia timer1 bez preskalera

    sei();                        // włącz obsługę przerwań

    while(1)  // Program główny
    {
       
    }    //zamyka while
    }   //zamyka main


    do przerwania wstawiłem zmienna LED_TOGGLE która zmienia stan wyjścia PC0 za każdym razem jak wejdzie do przerwania. Zmieniałem też wartośc początkową timera 0, czyli wpisywałem do TCNT0. Jak zauważyłem zmiana wartości nie zmienia długości sygnałów (stan wysoki i niski są niezmienne- obserwuje to na oscyloskopie), ale ciekawostką jest to że jak zmienie TCNT0 z 198 na 197 to zmienia się czas co jaki wywoływane jest przerwania ale potem mogę zmniejszać wartość TCNT0 nawet do 0 i to nic nie zmienia. Dlaczego się tak dzieje?

    Doszukałem się pewnej rzeczy. Jak wyrzucę to zwiększanie moich liczników

    Code:
        
    
        overflow1++;
        overflow2++;
        overflow3++;
        overflow_ADC++;   


    to przerwanie działa dobrze. Dlaczego się tak dzieje? może inaczej rozwiązać to iterację? muszę to tak rozwiązać bo potrzebuję odmierzać wiele czasów jednocześnie

    Dodano po 42 [minuty]:

    Kolejna spraw to fakt że gdy nie mam zadeklarowanych zmiennych przerwania działają dobrze ale jak tylko zacznę deklarować zmienne takie jak

    volatile char sw1a=0;
    volatile char sw1b=0;

    to przerwanie zaczyna wariować, teraz na oscyloskopie widzę w ogóle cuda bo zamiast sygnału prostokątnego o wypełnieniu 50% to widzę prostokąt o wypełnieniu jakiś 10% czyli raz przerwanie wywoływane jest szybko a raz wolno sam już nie wiem dlaczego tak jest :/ bardzo proszę o pomoc

    0 5
  • #2 08 Gru 2009 14:18
    _Robak_
    Poziom 33  

    Nie dziwne jak nie ustawiasz prescallera. Samo wywolanie obslugi troche trwa, ty zostawiasz sobie 57 cykli procesora kilka instrukcji, wyjscie z obslugi i ponowne wejscie. Przy takich ustawieniach to raczej tylko pisanie w asemblerze. Zwieksz prescaller do np. 64 i wtedy pewnie zobaczysz efekty.

    0
  • #3 08 Gru 2009 14:25
    nelik1987

    Poziom 31  

    zaraz sprawdzę ale ja murze odmierzać krótkie czasy i nie wiem czy to nie będzie przeszkadzać muszę trochę policzyć. Czyli po prostu jest za mało czasu pomiędzy przerwaniami i instrukcje wewnątrz nie nadążają się wykonać tak?

    0
  • #4 08 Gru 2009 14:38
    _Robak_
    Poziom 33  

    Moze nie do konca nie zdaza sie wykonac, ale przy wyjsciu z przerwania bedzie juz kolejne itp. Skonczyc sie skoncza, bo normalnie przerwania sa wylaczane podczas ich obslugi. w kazdym razie program nie bedzie dzialac prawidlowo i chyba nie ma sensu pisac dokladnie jak to bedzie wygladalo ;] Ja pisalem kiedys program ktory przy doliczeniu do 110 wywlywac mial przerwanie (w trybie CTC), to w C niestety nie dalo rady. W asemblerze jak najbardziej. Jednym z wyjsc jest zwiekszenie szybkosci taktowania procka.

    0
  • #5 08 Gru 2009 22:46
    BoskiDialer
    Poziom 34  

    Patrząc po temacie w którym okazało się, że winą dziwnej pracy uC był fusebit M103C można bez problemu opisać powstawanie błędu: spód stosu był niepoprawny (w m103 pamięć kończy się niżej), a więc powrót z przerwania był skokiem w losowe miejsce co kończyło się resetem procesora stąd niezależność od wpisanej wartości, jednak od pewnej krytycznej wartości, dla której czas pomiędzy wyjściem z przerwania a ponownym zainicjalizowaniem procesora po resecie był dłuższy od czasu przepełnienia timera następowało ponowne wejście do przerwania - jakkolwiek zachowanie musiało być bardzo losowe.

    0
  • #6 08 Gru 2009 23:13
    nelik1987

    Poziom 31  

    no i teraz już jest wszystko jasne dziękuję bardzo wszystkim za pomoc. Program już śmiga teraz piszę jego darzą część. Wkrótce opublikuję cały projekt

    0