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

[Atmega16][C][AVR Studio] Problem z przerwaniem od licznika

svensonie 06 Lis 2010 19:30 1771 5
REKLAMA
  • #1 8710612
    svensonie
    Poziom 11  
    Witam, mam problem z uzyskaniem przerwania od licznika. Program w ogólności ma co mniej więcej sekundę na przemian zapalać i gasić diode. Licznik jest w trybie porównania do wartości 156. Częstotliwość oscylatora to 4 MHz, przeskalowana przez 256. Program niestety nie chce wejść w przerwanie. Może któryś z bardziej doświadczonych forumowiczów jest w stanie zwrócić mi uwage gdzie robię błąd ewentualnie o czym zapomniałem.

    Kod programu:
    Cytat:

    #define F_CPU 4000000UL /* 4 MHz */
    #include <avr/io.h>
    #include <avr/interrupt.h>


    int8_t licznik = 0;
    int8_t licz = 0;

    ISR (TIMER0_COMPA_vect)
    {
    ++licznik;
    }

    int main (void) {

    DDRA = 0xFF;
    PORTA &= ~_BV(PA0);
    PORTA |= _BV(PA1);
    PORTA &= ~_BV(PA2);
    //kofiguracja oobsługi przerwania licznika
    TCCR0 = _BV(CS02); //preskaler


    TCCR0 = _BV(WGM01);//tryb pracy licznika
    TCCR0 = ~_BV(WGM00);

    OCR0 = 0x9C; //156; //do ilu ma zliczac licznik
    TIMSK = _BV(OCIE0); //odblokowanie przerwania

    sei();
    while(1) {
    if(licznik == 154) {
    ++licz;
    if (licz == 100) {
    PORTA ^= _BV(PA0);

    dupa = 0;
    }
    }
    }
    return 0;
    }
  • REKLAMA
  • #2 8710650
    tadzik85
    Poziom 38  
    Cytat:
    TCCR0 = _BV(CS02); //preskaler
    
    
    TCCR0 = _BV(WGM01);//tryb pracy licznika
    TCCR0 = ~_BV(WGM00); 


    Nad tym się zastanów, jaką wartość będzie miał ten rejestr po tych 3 operacjach. Konstrukcja pętli głównej jest do.... Jeśli licznik = 154 to jakim cudem może jednocześnie równać się 100?
  • REKLAMA
  • #3 8710661
    Samuraj
    Poziom 35  
    Coś namieszałeś w tym kodzie. Licznik sam z siebie liczy a ty w przerwaniu ustawiasz co ma robić.
    U Ciebie to wygląda tak że w pętli głównej sprawdzasz do ilu policzył licznik a w przerwaniu inkrementujesz jego wartość ?

    Pomyśl raz jeszcze do czego służy przerwanie od Timera i pomyśl jak to powinno być zrobione.
    Podpowiem że wszystko powinno wykonywać się w przerwaniu z pominięciem pętli głównej - zegar sobie liczy w tle a po osiągnięciu danej wartości przechodzić do przerwania.
  • REKLAMA
  • #4 8713821
    svensonie
    Poziom 11  
    Tak wygląda kod po poprawkach:
    Cytat:

    #define F_CPU 4000000UL /* 4 MHz */
    #include <avr/io.h>
    #include <avr/interrupt.h>


    int8_t licznik = 0;


    ISR (TIMER0_OVF_vect)
    {
    ++licznik;
    if (licznik == 100) {
    PORTA ^= _BV(PA0);
    licznik = 0;
    }
    }

    int main (void) {

    DDRA = 0xFF;
    PORTA &= ~_BV(PA0);
    PORTA |= _BV(PA1);
    PORTA &= ~_BV(PA2);
    //kofiguracja oobsługi przerwania licznika
    TCCR0 |= _BV(CS02); //preskaler

    TCCR0 |= _BV(WGM01);//tryb pracy licznika
    TCCR0 &= ~_BV(WGM00);

    OCR0 = 0x9C; //156; //do ilu ma zliczac licznik
    TIMSK = _BV(OCIE0); //odblokowanie przerwania

    sei();
    while(1) {

    }
    return 0;
    }


    Mam warażenie, że ja źle skofigurowałem przerwanie. Jestem początkujący i jeszcze troche gubie się w obsłudze tych przerwań.
  • REKLAMA
  • #5 8713852
    tadzik85
    Poziom 38  
    Albo tryb CTC i przerwania od niego albo normalny tryb pracy i przerwanie od przepełnienia.
  • #6 8719099
    svensonie
    Poziom 11  
    tadzik85 napisał:
    Albo tryb CTC i przerwania od niego albo normalny tryb pracy i przerwanie od przepełnienia.


    W porównaniu do ostatniej wersji zmieniłem ISR (TIMER0_OVF_vect) na ISR (TIMER0_COMP_vect) i działa. Po prostu w zestawieniu nazw wektorów przerwań z których korzystałem nie było TIMER0_COMP_vect i stąd te zamieszanie. Dzięki wielkie :) Problem rozwiązany
REKLAMA