Skocz do zawartości

Przerwania od timera w trybie CTC Arduino Nano


Daniel_1995

Pomocna odpowiedź

Witam mam problem z uruchomieniem przerwania do sterowania diodą w Arduino Nano. Chcę to wykonać na timerze pracującym w trybie CTC oraz przerwaniu. Niestety program wykonany przeze mnie nie działa. Czy mógłby mi ktoś wytłumaczyć dlaczego? Program piszę w Arduino IDE ale w taki sposób jak na czystą Atmegę 328p. Poniżej kod:

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define LED (1<<PB5) 
#define LED_TOGG PORTB ^= LED      //zmiana stanu diody
volatile uint8_t x=0;              //zmienna do zliczania wartości

int main(void) {
 DDRB |= (1<<PB5);                //kierunek wyjsciowy
 TCCR0A |= (1<<WGM01);            //ustawienie trybu CTC
 TCCR0B |= (1<<CS02) | (1<<CS00); //Ustawienie preskalera
 TIMSK0 |= 0x2;                   //Zezwolenie na przerwania 
 OCR0A = 125;                     //ustawienie wartości rejestru porównania
  sei();                           //zezwolenie na globalne przerwania

while(1);
}




ISR(Przerwanie_vect){               //Funkcja obsługi przerwania
 if(x==125){
 LED_TOGG;
 }else{
 x++;
 }
}
Link do komentarza
Share on other sites

W Arduino IDE nie możesz w prosty sposób pisać jak na "czystą ATmegę". Twój plik źródłowy jest poważnie przerabiany i kompilator wcale nie dostaje tego co napisałeś.

Arduino używa Timera 0 do własnych potrzeb - poczytaj o tym, bo nie czas i miejsce by to znowu wałkować. Użyj Timera 2 - jest podobny do zerowego a przynajmniej masz pewność, że nikt Ci go nie "podbierze". Co to jest "Przerwanie_vect"??

EDIT: Spróbuj zamiast "Przerwanie_vect" wstawić konkretny, predefiniowany dla ATmega328 wektor. W przypadku timera 0 i przerwania OCIE0A będzie to TIMER0_COMPA_vect. Dokładnie w tej pisowni.

EDIT2: Jeśli do OCR0A wpiszesz 125, to okres będzie miał 126 cykli zegara (tego po preskalerze) - tak miało być?

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Przestawiłem kod na Timer 2 ale dalej nic z tego, czas kupić czystą Atmegę.

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define LED (1<<PB5) 
#define LED_TOGG PORTB ^= LED      //zmiana stanu diody
volatile uint8_t x=0;              //zmienna do zliczania wartości

int main(void) {
 DDRB |= (1<<PB5);                //keirunek wyjsciowy
 TCCR2A |= (1<<WGM21);            //ustawienie trybu CTC
 TCCR2B |= (1<<CS02) | (1<<CS01) | (1<<CS00); //Ustawienie preskalera
 TIMSK2 |= 0x2;                   //Zezwolenie na przerwania 
 OCR2A = 124;                     //ustawienie wartości rejestru porównania
 sei();                           //zezwolenie na globalne przerwania

while(1);
}




ISR(TIMER2_COMP_vect){               //Funkcja obsługi pzrerwania
 if(x==125){
 LED_TOGG;
 }else{
 x++;
 }


}
Link do komentarza
Share on other sites

Łatwo rezygnujesz.

Nie wpisałeś wektora tak jak prosiłem. W przypadku Timera 2 ma być "TIMER2_COMPA_vect". No i nie zerujesz licznika x w przypadku osiągnięcia wartości 125, ale to mały szczegół 🙂

Z tymi wektorami jest tak, że jest ich zdefiniowanych całe mnóstwo. Akurat to co wpisałeś, czyli TIMER2_COMP_vect jest tylko dla ATmega32 i oczywiście pokazuje inne miejsce niż poprawne dla mega328.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dzięki własnie zapomniałem o zerowaniu zmiennej. Teraz rozumiem, zastanawiające jest jeszcze jedno jeśli w rejestrze TIMSK2 ustawię wartość 0x7 również nie działa, czy to oznacza ze jeśli ustawimy przerwanie na obu portach to musi zostać zdefiniowany wektor przerwania a jeżeli wektora brak to układ będzie się resetował?

Link do komentarza
Share on other sites

Co to znaczy "przerwanie na obu portach"? Timer 2 generuje trzy różne zdarzenia które mogą być przerwaniem, każde z innym wektorem. Możesz odblokowywać tylko te których obsługę napisałeś w formie funkcji ISR() z odpowiednim wektorem wpisanym w nawiasy. Kompilator w każdy niewykorzystany wektor wstawia skok do adresu 0. Jeżeli więc zostanie wygenerowane przerwanie które nie ma podłożonej "swojej" funkcji ISR, wykonana się programowy restart kodu. W tym przypadku do TIMSK2 powinieneś wpisać 0x02 czyli odblokować wyłącznie OCIE2A, bo tylko to obsługujesz swoją funkcją.

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...