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

[ATmga128][C] Nieobliczane przerwanie od timera 0

nelik1987 08 Gru 2009 13:28 1617 5
REKLAMA
  • #1 7361122
    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:

    #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

        
        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
  • REKLAMA
  • #2 7361286
    _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.
  • REKLAMA
  • #3 7361304
    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?
  • REKLAMA
  • #4 7361355
    _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.
  • REKLAMA
  • #5 7364095
    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.
REKLAMA