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
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.
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...
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.
Wenn du ISR(TIMER1_COMPB_vect)verwendest musst du auch OCIE1B im TIMSK setzen und nicht OCIE1A oder umgekehrt.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.