Forum: Mikrocontroller und Digitale Elektronik Mega8: Timer 2 Interrupt-Problem??


von Christoph S. (mixer) Benutzerseite


Lesenswert?

Hallo,

ich möchte mit dem Timer 2 vom Mega8 2 Interrupts auslösen, einmal bei 
Compare und einmal bei Overflow.
Habe Takt eingestellt und beide Interrupts freigegeben, das 
Compareregister mit dem entsprechenden Wert geladen!
Wenn jetzt der Compare-Interrupt auftritt, dann springt der Simulator 
nach dem "reti" auf den Overflow-Interrupt!?!
Habe ich da im Datenblatt was übersehen wie ich den genau initialisieren 
muss oder funktioniert das gar nicht, dass ich mit einem Timer 2 
Interrupts auslösen kann??

MFG Mixer

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Bedenke, dass der Timer weiterläuft, wenn der Compare-Interrupthandler 
(die ISR dafür) am schuften ist!

Wenn dabei ein Overflow auftritt, ist der Interrupt dafür in 
Lauerstellung bis der aktuelle Compare-Interrupthandler fertig ist. Nach 
dem RETI des Compare-ISR wird der Overflow-Interrupthandler 
angesprungen... genau das Bild, das du beschreibst.

Abhlfe?

Hmm, überlegen, ob du wirklich die beiden Interrupts auf dem gleichen 
Timer haben willst.

Und ob du überhaupt beide Interrupts brauchst oder ob es einer, ggf. 
geschickter gewählter, auch tun würde.

Was willst du eigentlich machen?

von Christoph S. (mixer) Benutzerseite


Lesenswert?

Der Compare-Interrupt sollte eigentlich 1 ms nach dem Overflow kommen, 
und der Abstand von Overflow zu Overflow sollte ca. 20ms betragen.

Ich möchte damit eine Servosteuerung machen, und da der Impuls ja immer 
min. 1ms lang ist, hab ich mir gedacht, kann der AVR ja die 1ms mit nem 
Interrupt überbrücken und da ggf. was anderes machen!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Also du willst, alle 20ms die Möglichkeit haben, einen Puls an den Servo 
zu schicken und der Puls ist 1 ms lang.

Und du dachtest, dass du den Overflow-Interrupt als Zeitscheibe 
verwendest aber das Ende des Pulses über den Compare-Interrupt abpasst.

Dann würde ich den Compare-Interrupt nicht ständig erlauben. Nur wenn 
der Overflow-Interrupt ausgelöst hat und ein Puls an den Servo unterwegs 
ist. Die Einstellung sollte so sein, dass 1ms später als "jetzt" (d.h. 
Zustand im Overflow-ISR) der Compare-Interrupt kommen soll, Danach nur 
den Compare-Interrupt wieder disablen.

Und genereller Tip: Beide ISRs knapp halten.

von Christoph S. (mixer) Benutzerseite


Lesenswert?

Das ist ja schön und gut, aber wenn nach 1ms der Compare-Interrupt 
ausgelöst wird und dann mit "reti" wieder beendet wird, dann springt er 
sofort auf den Overflow-Interrupt, obwohl er ja da nichts zu suchen 
hat!!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

In Echt oder nur im Simulator?

Wenn du es in Echt noch nicht testen kannst, bring  Beispielcode bei. 
Ich lasse das dann auf einem Atmega8 laufen (heute abend).

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Mixer S. wrote:
> Das ist ja schön und gut, aber wenn nach 1ms der Compare-Interrupt
> ausgelöst wird und dann mit "reti" wieder beendet wird, dann springt er
> sofort auf den Overflow-Interrupt, obwohl er ja da nichts zu suchen
> hat!!

Solche Antworten "liebe" ich. Null neue Information und das Gesagte von 
einem Ohr rein und zum anderen raus.

von Christoph S. (mixer) Benutzerseite


Angehängte Dateien:

Lesenswert?

Sorry, war grad falsch, hier kommt die richtige:

Ist sowohl auf m Simulator als auch auf m AVR so, hab s mit m Oszi
betrachtet.

Der Code soll zuerst den Timer initialisieren und PB1 auf "high" setzen,
dann soll nach 1ms der Compare-Interrupt einspringen und je nach Wert
für den Servo eine bestimmte Zeit warten bis der PB1 auf "low" gesetzt
wird. 20ms nach dem Start soll dann der Timer Overflow den PB1 wieder
auf "low" setzen und das spiel geht von vorne los

Hab die Schleifen, Prescaler usw. für Simulation optimiert, damit das
immer nicht so lange dauert ansonnsten Originalcode!

von Christoph S. (mixer) Benutzerseite


Lesenswert?

Sorry, da ist mir ein Fehler unterlaufen, jetzt ist aber der richtige 
Code da!

von Peter D. (peda)


Lesenswert?

Mixer S. wrote:
> Das ist ja schön und gut, aber wenn nach 1ms der Compare-Interrupt
> ausgelöst wird und dann mit "reti" wieder beendet wird, dann springt er
> sofort auf den Overflow-Interrupt

Das ist unmöglich!
Er muß nach dem RETI immer einen Befehl der Mainloop ausführen.

Wenn der Compare-Interrupt zu lange dauert, kann durchaus ein Overflow 
erreicht werden.
Delays in Interrupts sind immer gefährlich.
Schau dochmal in den Simulator, wie das Overflowbit vor dem RETI steht.


Peter

von Christoph S. (mixer) Benutzerseite


Lesenswert?

>Das ist unmöglich!

Das hab ich mir auch gedacht, darum hab ich ja auch diesen Thread 
gestartet!

Bei der Simulation wird das Bit für nen Overflow Interrupt nicht 
gesetzt, und der Timer ist auch noch weit weg von nem Overflow!

Kann des sein, dass des an der Initialisierung des Timers liegt?? Evtl. 
muss man da noch n bit setzen oder so, hab das Datenblatt nicht ganz 
überblickt!

von Michael U. (amiga)


Lesenswert?

Hallo,

mit welchem Wert wird delay initialisiert?
Warum vergleichst Du mit brlo und machst nicht den Abbruch bei gleich 
mit breq? brlo kann nette Effekte erzeugen, wenn man einen möglichen 
Überlauf durch 0 übersieht.

Due rettest weder SREG noch die benutzten Register in den ISR, spielt 
hier zwar vermutlich keine Rolle, sollte man sich aber generell 
angewöhnen, spart später viel Zeit bei der Fehlersuche.

Warum diese seltsame Springerei? Macht es schwer lesbar...
Ein Programm sollte möglichste in der Folge des Ablaufs geschrieben 
sein.

Gruß aus Berlin
Michael

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Du darfst oben in der Vektortabelle kein rcall benutzen! Dort gehört 
ein rjmp hin. Am Rest bin ich noch am schauen.

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

So hier meine Kommentare und Änderungen. Der Code macht jetzt das, was 
ich mir vorstelle, was du haben willst ;-)

Nicht verstanden habe ich allerdings die Sache mit dem delay und servo. 
Das habe ich grosszügig auskommentiert bzw. der Code wird nicht 
angesprungen. Da müsstest du nacharbeiten.

Jetzt passiert folgendes:

Bei 8 MHz Takt alle (ca.) 20 ms PB1 HIGH über den Overflow Interrupt von 
Timer2 und 1 ms später PB1 LOW über den Compare Match Interrupt von 
Timer2.

Die Vorladewerte für TCNT2 habe ich von dir übernommen (TCNT2 100 bzw. 
CTC 8 Timertakte später = 108). Dein Prescaler 8 kommt mir spanisch vor, 
daher habe ich den auf 1024 hochgesetzt. Mit 1024 sieht es für mich 
sinnvoll aus:

Vorladewert 100 ergibt 256-100 = 156 Timertakte bis Overflow. * 
Prescaler 1024 sind das 159744 Maschinentakte und bei 8 MHz sind das 
1/50,08 s d.h. ca. 20 ms.

Vorladewert 108 für das Vergleichsregister bei einem Vorladewert von 100 
für das Timerregister ergibt 108-100 = 8 Timertakte * Prescaler 1024 
sind das 8192 Maschinentakte und bei 8 MHz sind das 1/976,5625 s, d.h. 
1,024 ms

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Mixer S. wrote:

> Der Code soll zuerst den Timer initialisieren und PB1 auf "high" setzen,
> dann soll nach 1ms der Compare-Interrupt einspringen und je nach Wert
> für den Servo eine bestimmte Zeit warten bis der PB1 auf "low" gesetzt
> wird. 20ms nach dem Start soll dann der Timer Overflow den PB1 wieder
> auf "low" setzen und das spiel geht von vorne los

Ups. Das habe ich mir ganz oben anders zusammengereimt. Also Kommando 
zurück, meine Änderungen am Code machen das nicht. Ich schaue mir das 
noch mal an.

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

So hier die Änderung.

von Christoph S. (mixer) Benutzerseite


Lesenswert?

Hallo,

Danke für deine Mühe!! Das rcall war der Auslöser, dass danach der 
Overflow Interrupt kommt!!
Den Rest muss ich mir noch genau anschauen, aber rein vom überfliegen 
siehts gar net so schlecht aus!
MFG Mixer

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.