Forum: Mikrocontroller und Digitale Elektronik avr-gcc: Interrupts führen zu "verkehrtem" PWM


von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Hi zusammen,

ich hab hier ein kniffliges Phänomen, und (nach langem Suchen) glaube 
ich die Ursache gefunden zu haben. ich hätte gerne eure bestätigung, und 
eine idee was ich dagegen tun kann.

Gegeben ist eine "Halb-Soft-PWM" auf zwei Pins mit Timer2: Dieser läuft 
mit Prescaler 8 (bei 16 MHz CPU-Takt also mit 2 MHz), es sind zwei 
Output-Compares drinnen und der "normale" Overflow-Handler bei 255 (also 
kein CTC und auch kein implizites Schalten der Ausgänge)

In der ISR(TIMER2_OVF_vect) werden beide Pins auf High gesetzt; in den 
ISR(TIMER2_COMP[A|B]_vect) wird der entsprechende Pin wieder auf low 
gezogen. Über die OCR(A,B) wird die PWM-Pulsweite gesteuert. Die ISRs 
sind "as sinmple as possible", bestehen im Wesentlichen nur aus einem 
sbi/cbi.
Soweit, so gut, funktioniert prächtig.

Nun ist auch noch Timer0 dazugekommen, ebenfalls mit Prescaler 8, der 
overflow-handler ist etwas komplexer (aber vergleichsweise auch noch 
sehr einfach) aber der wird schon eine handvoll Takte verbraten.

Arbeite ich nun mit sehr kleinen PWM-Werten (1..3) so passiert es 
nachvollziehbar, dass sich das PWM-Signal "umdreht", ich also 
kontinuierlichen High-Pegel mit ganz kurzen Spitzen nach low kriege. 
Sobald ich den PWM-Wert in den OCR(a,B) erhöhe, normalisiert sich das 
Bild wieder.

So, nun mein Verdacht: Der Interrupt-Handler für Timer0 wird 
abgearbeitet, und genau während dieser zeit laufen sowohl der Overflow- 
als auch (wenige Takte später) der Output-Compare-interrupt auf. beide 
interrupts-Handler werden momentan nicht aufgerufen, da ja grad ein 
anderer handler läuft, und interrupts global deaktiviert sind. Aber die 
Interrupts werden "gespeichert" und nachdem der Timer0-handler fertig 
ist, in der Reihenfolge ihrer Priorität nach aufgerufen. Nun hat der 
Compare-Match-Vektor eine höhere Priorität als der Overflow-handler, die 
handler werden also in der genau verkehrten Reihenfolge aufgerufen...

Frage: ist meine Erklärung schlüssig?

Wenn ja, was tun? ich sehe folgende Möglichkeiten:

- per Preload der Timer-Values diese so setzen, dass sie möglichst 
"entfernt" voneinander ablaufen (ich hätte mal 192 genommen, da ich nie 
mit so hohen PWM-Werten arbeiten werde)

- Im Interrupt-Handler vom Timer0 ander interrupts zulassen 
(dangaruuuhs)

Sonstige ideen?


lg Michi

von Stefan (Gast)


Lesenswert?

Ich würde im Timer0 Interrupt andere Interrupts zulassen.

von Stone (Gast)


Lesenswert?

>Nun ist auch noch Timer0 dazugekommen, ebenfalls mit Prescaler 8, der
>overflow-handler ist etwas komplexer (aber vergleichsweise auch noch
>sehr einfach) aber der wird schon eine handvoll Takte verbraten.

Wenn sie eh Zeitgleich überlaufen, kannst du nicht den Overflow-Handler 
von Timer 0 in die ISR des Timer 2 packen.


Gruß Matthias

von Gerd E. (robberknight)


Lesenswert?

Michael Reinelt schrieb:
> Frage: ist meine Erklärung schlüssig?

Wenn Du Timer0 deaktivierst und dann das Problem nicht mehr auftritt, 
klingt das nach ner plausiblen Erklärung.

> Sonstige ideen?

Du könntest im Compare-Match-Vektor abfragen, ob das Interrupt-Flag für 
den Overflow gesetzt ist. Damit kannst Du den Fall erkennen.

Wenn es nicht so wichtig ist den Zyklus exakt einzuhalten, könntest Du 
dann diesen einen Zyklus ausfallen lassen und z.B. den nächsten dann 
doppelt so lang machen.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Gerd E. schrieb:
> Du könntest im Compare-Match-Vektor abfragen, ob das Interrupt-Flag für
> den Overflow gesetzt ist. Damit kannst Du den Fall erkennen.

Ha! Wusst ichs doch dass es eine simple und effektive lösung gibt! Danke 
vielmals!

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Stone schrieb:
>>Nun ist auch noch Timer0 dazugekommen, ebenfalls mit Prescaler 8, der
>>overflow-handler ist etwas komplexer (aber vergleichsweise auch noch
>>sehr einfach) aber der wird schon eine handvoll Takte verbraten.
>
> Wenn sie eh Zeitgleich überlaufen, kannst du nicht den Overflow-Handler
> von Timer 0 in die ISR des Timer 2 packen.
>
>
> Gruß Matthias

Mittlerweile weiss ich dass sie nicht zeitgleich laufen werden, da Timer 
0 ein CTC benötigen wird. Damit scheidet auch meine "Preload" Variante 
aus.

Aber der Vorschlag von robberknight zusammen mit dem zulassen von 
interrupts im timer0-handler wird das problem wohl aus der Welt 
schaffen.

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.