Forum: Mikrocontroller und Digitale Elektronik ISR(TIMER1_COMPA_vect) und OCR1A


von Alexander G. (grossmann200)


Lesenswert?

Hallo zusammen,
nach dem Studium einiger Tutorials und Internetsuche habe ich mich nun 
daran gewagt meinen ersten Interrupt zu programmieren.

Ich habe mal meine Frage in zwei Versionen aufgeführt. Irgendwie dachte 
ich die Langversion ist zu kompliziert und zu lang, und die Kurzversion 
erklärt's vielleicht nicht richtig.


Meine Frage in Kurzversion:
Ist in ISR(TIMER1_COMPA_vect) der richtige Vektor gewählt, wenn ich die 
Routine jedesmal aufrufen will, wenn mein Vergleichswert in OCR1A 
erreicht wird.

Meine Frage in Langeversion:
In meinem Progrämmchen (zur PWM - dass dank Forenhilfe auch flutscht) 
wird der Zähler mit dem Vergleichwert (OCR1A) verglichen. Wenn ich das 
Atmel-Datenblatt richtig verstanden habe, dann wird bei jeder 
Übereinstimmung von Vergleichswert mit Zählwert ein Output Compare 
Interrupt Request (OCF1A/B) ausgelöst. An anderer Stelle fand ich eine 
Tabelle mit Interrupt-Vektoren. Da auch das AVR-Tutoral von Vektoren als 
Argumenten für ISR spricht, habe ich dann mal

ISR(TIMER1_COMPA_vect) { //Anweisungen }

gewählt. In main() habe ich dann auch mit sei() brav den Global 
Interrupt Enable Bit gesetzt. Beim compilieren gibt's auch keine Fehler. 
Ich dachte jetzt, dass jedesmal wenn Zählwert = Vergleichswert eintrifft 
meine Interrupt-Routine ausgelöst wird ... tut's allerdings nicht. Da es 
von mir eine Annahme war, dass TIME1_COMPA_vect der richtige Vektor sei, 
frage ich mal hier, ob dem so ist (leider steht im Datenblatt nichts 
näheres dazu ... oder ich raff's einfach nicht.

Grüße
Der Alexander

von Hubert.G (Gast)


Lesenswert?

Ich weis nicht welchen Kontroller du hast aber ich denke mal dir fehlt 
noch der Eintrag im TIMSK-Register für OCIE1A. Im Datenblatt unter 
Output Compare Units.

von ??? (Gast)


Lesenswert?

Im Prinzip stimmt das!
Es könnte sein, dass du ISR(TIMER1_COMPB_vect) verwenden musst.
Wichtig ist, dass nicht nur die globalen Interrupts eingeschaltet sind, 
sondern auch der für diesen Betriebsmodus. Natürlich muss auch der Timer 
in den gewünschten Modus gebracht werden. Das steht aber im Datenblatt 
geschrieben. Poste sonst mal den ganzen Code...

von Alexander G. (grossmann200)


Lesenswert?

ISR(TIMER1_COMPB_vect) hat leider auch nicht funktioniert.

Neben den Global Interrupt Enable Bit habe ich schon geschaut, ob sonst 
noch was aktiviert werden muss. Ich habe auch unter 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Interrupts etwas 
für die beiden externen Interrupts gefunden (GICR Register), jedoch 
nichts für den Fall, wenn der Zähler den Vergleichwert erreicht. Aber 
anscheinend habe ich hier tatsächlich was übersehen und dies wäre des 
Problems Lösung. Hier mal mein Code:

#include <avr/io.h>
#include <avr/interrupt.h>


ISR(TIMER1_COMPB_vect) // Schaltet LED an PB0 ein
{
  DDRB = DDRB | (1 << PB0);
  PORTB = PORTB | (1 << PB0);
}


int main(void)
{
// PWM: Bringt LED an PB1 zum blinken
DDRB = DDRB | (1 << PB1);
TCCR1B = TCCR1B & ~(1 << WGM13);
TCCR1B = TCCR1B | (1 << CS10);
TCCR1B = TCCR1B | (1 << CS12);
TCCR1A = TCCR1A | (1 << WGM10);
TCCR1A = TCCR1A | (1<< WGM11);
TCCR1A = TCCR1A | (1 << COM1A1);
TCCR1A = TCCR1A | (0 << COM1A0);
OCR1A = 400;

//Interrupts aktivieren
TIMSK = TIMSK | (1 << OCIE1A);
sei();

while(1)
  {
  };
}


Ach ja, ich habe einen ATMega8.

von Hubert.G (Gast)


Lesenswert?

Wenn du ISR(TIMER1_COMPB_vect)verwendest musst du auch OCIE1B im TIMSK 
setzen und nicht OCIE1A oder umgekehrt.

von Alexander G. (grossmann200)


Lesenswert?

Verdammt. Klar, des isses. Ist mir jetzt auch irgendwie peinlich. Vor 
lauter hin- und herspringerher zwischen Tutorials, Datenblatt, Foren, 
Internetsuche habe ich da echt den Überblick verloren. Im Code isses mir 
dann auch nicht aufgefallen, da dieser im Original etwas unübersichtlich 
wurde da ich mir hinter jeder Zeile eine mehrzeilige Kommentierung 
geschrieben habe.

Eines würde mich als Anfänger dann doch noch interessieren. Wie auch 
???(Gast) schon angemerkt hat, muss auch im TIMSK-Register das OCIE1A 
Bit gesetzt werden. Ich bin im Datenblatt da eher zufällig drüber 
gestolpert (steht auf S.72). Während das setzen der Vektoren irgendwo 
ganz am Anfang steht. Gibt es hier sowas wie eine Regel, anhand der man 
erkennt, was man alles setzen muss ... oder muss man sowas einfach nur 
wissen. Sprich man lernt es mit der Zeit. Da es mir auch etws unangnehm 
ist in Foren sowas doch recht einfaches zu fragen, war ich gestern im 
Buchladen und hoffte eine übersichtliche Literatur zu finden, habe 
jedoch nix gefunden. Kannst du hier etwas empfehlen.

Also nochmals danke, und hoffe ihr verzeiht mir, dass ich durch meine 
Schlamperei eure Zeit beansprucht habe.

Grüße
Der Alexander

P.S. Vielleicht sollte man, wenn's mal nicht funktioniert, einfach mal 
ne' Pause machen.

von Joerg X. (Gast)


Lesenswert?

Für jeden Interrupt, den du benutzen willst brauchst du eine ISR (der 
exakte Name hängt vom compiler ab), musst diesen Interrupt aktivieren- 
beim AVR fast immer ein Bit mit der Bezeichnung xxxIE (-interrupt 
enable) und musst die Interrupte mit "sei" global aktivieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.