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

GCC, ATMega8 (8MHz), Timer1 i problem z odliczanie 1s

^saint^ 07 Cze 2007 17:00 3397 12
REKLAMA
  • #1 3962674
    ^saint^
    Poziom 11  
    Posty: 24
    Ocena: 7
    Witam
    Mam jakiś błąd w programie ale nie mogę dojść gdzie.
    Przed mian'em mam obsługę przerwania dla SIG_OUTPUT_COMPARE1A
    która teoretycznie powinna się wywoływać co 1s. Timer1 ustawiony w tryb compare na preskalerze 256, ustawienia timera są na początku maina.

    SIGNAL(SIG_OUTPUT_COMPARE1A) // sygnal porownania od timera 1A
    {
    	sec++;
    	sec%=60;
    }
    
    //------------------------------------------------------------------------------
    int main(void) //program główny
    {
    
    	//--------------- TIMER1 ----------------------
    	TCCR1B |= 0x04; //preskaler ustawiony na 256
    
    	TCNT1H = 0;   //wartość początkowa
    	TCNT1L = 0;
    	OCR1AH = 0x7A;	//7A12 = 31250 -> 1s
    	OCR1AL = 0x12;
    					
    	TIMSK = 0x10;    //przerwanie gry osagnięta wartosc = OCR1A
    
    	//---------------------------------------------
    	sei();


    I niestety coś jest nie tak ponieważ niezależnie jaki preskaler ustawie czy jaka wartość dam do OCR1A to przerwanie jest wywoływanie zawsze co około 2 sekundy
  • REKLAMA
  • #2 3962910
    _Robak_
    Poziom 33  
    Posty: 2209
    Pomógł: 231
    Ocena: 29
    Przydalby sie caly program;)
  • #3 3962979
    ^saint^
    Poziom 11  
    Posty: 24
    Ocena: 7
    Nie wiem czy chcesz czytać 600 linii kodu ;)
    Mogę tylko powiedzieć że sprawdziłem cały kod i nigdzie więcej nic z przerwaniami nie robie
  • REKLAMA
  • #5 3963086
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    ^saint^ napisał:
    I niestety coś jest nie tak ponieważ niezależnie jaki preskaler ustawie ...

    To mnie dziwi , bo zmiana preskalera , powinna powodować zmianę częstotliwości , z jaką wywoływane jest przerwanie.
    ^saint^ napisał:
    czy jaka wartość dam do OCR1A to przerwanie jest wywoływanie zawsze co około 2 sekundy

    To mnie nie dziwi , bo w trybie w którym aktualnie pracuje Twój Timer , zawartość OCR1A nie ma wpływu na częstotliwość przerwań.

    Piotrek
  • REKLAMA
  • #6 3963160
    _Robak_
    Poziom 33  
    Posty: 2209
    Pomógł: 231
    Ocena: 29
    Juz chyba wiem gdzie jest blad, zakladajac ze licnzik pracuje w trybie normalnym to przerwanie powinno byc wywolywane takim makrem:
    
    ISR(TIMER1_OVF_vect)
    {...}
    


    Bo przeciez Twoj licznik nie pracuje w trybie CTC a dla tego trybu jest uzyte przez Ciebie makro.
  • #7 3963333
    ^saint^
    Poziom 11  
    Posty: 24
    Ocena: 7
    Z tym |= i = juz kombinowałem i nic nie dało.
    Ja nie chce overflow dlatego mam OCR1A ustawione i używam trybu compare i wpisuje TIMSK = 0x10 żeby włączyć porównywanie z OCR1A.
  • #8 3963347
    _Robak_
    Poziom 33  
    Posty: 2209
    Pomógł: 231
    Ocena: 29
    Jezeli w programie pozniej nic nie zmieniasz to twoj licnzik pracuje w trybie normal;)

    Zeby byl w trybie CTC musialbys uwstawic bit WGM12!! bit OCIE wlacza tylko przerwania dla trybu CTC!!
    Ustaw TCCR1B
    [/code]
  • #9 3963370
    ^saint^
    Poziom 11  
    Posty: 24
    Ocena: 7
    Ale w takim razie musze obsłużyć nie SIG_OUTPUT_COMPARE1A tylko coś innego ale co???
    Ja chciałem robic porównanie do wartości granicznej (ustawionej przeze mnie) a nie do overflow
  • REKLAMA
  • #10 3963394
    _Robak_
    Poziom 33  
    Posty: 2209
    Pomógł: 231
    Ocena: 29
    Rozumiem:) ale nie ustawiles bitu WGM12 ktory by ten tryb uruchomil, jezeli ustawisz tylko bit CS12 to licznik dziala w trybie normal
  • #11 3963419
    ^saint^
    Poziom 11  
    Posty: 24
    Ocena: 7
    Ustawiłem chyba tak jak mówisz tzn.
    TCCR1B=0xC;
    i
    ISR(TIMER1_OVF_vect) {sec++;sec%=60;}
    ale niestety sec jest cały czas = 0
  • Pomocny post
    #12 3963461
    _Robak_
    Poziom 33  
    Posty: 2209
    Pomógł: 231
    Ocena: 29
    :):)
    I znowu na odwrot:)
    Jak ustawisz
    TCCR1B=0xC;

    Czyli to o co Ci chodzi(tryb CTC)
    to musisz zostawic makro wywolujace przerwanie takie jakie miales:)
    SIGNAL(SIG_OUTPUT_COMPARE1A)

    ale radzilbym zmienic na taka nazwe:
    ISR(TIMER1_COMPA_vect)
  • #13 3963488
    ^saint^
    Poziom 11  
    Posty: 24
    Ocena: 7
    Dobra wielkie dzięki już działa dokładnie jak mówiłeś
    TCCR1A=0xC
    a przerwanie na ISR(SIG_OUTPUT_COMPARE1A) lub TIMER1_COMPA_vect

Podsumowanie tematu

LABEL_AI_GENERATED
Problem dotyczył nieprawidłowego działania przerwania TIMER1 na mikrokontrolerze ATMega8 pracującym z zegarem 8 MHz i preskalerem 256. Użytkownik ustawił Timer1 w trybie porównania (compare) z wartością OCR1A na 31250, oczekując wywołania przerwania co 1 sekundę, jednak przerwanie było wywoływane ciągle, niezależnie od ustawień preskalera i OCR1A. W dyskusji zwrócono uwagę, że Timer1 domyślnie pracuje w trybie normalnym, a do trybu CTC (Clear Timer on Compare Match) konieczne jest ustawienie bitu WGM12 w rejestrze TCCR1B. Przerwanie dla trybu CTC powinno być obsługiwane przez ISR(TIMER1_COMPA_vect) zamiast przestarzałego SIG_OUTPUT_COMPARE1A. Po poprawnym ustawieniu TCCR1B=0x0C (CTC z preskalerem 256) oraz użyciu właściwego wektora przerwania ISR(TIMER1_COMPA_vect) program zaczął działać zgodnie z oczekiwaniami, wywołując przerwanie co 1 sekundę i inkrementując zmienną sekundową.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA