Forum: Mikrocontroller und Digitale Elektronik Interrupt prescaler ändern


von Marco G. (arccra)


Lesenswert?

Hallo zusammen,

ich programmiere einen ATMega32u4 in ASM und habe folgende Frage:

Ich würde gerne den Prescaler des Timer-Interrupts am Ende der 
Interrupt-Routine ändern. Ist dies ohne weiteres möglich? Hier ein 
grobes Beispiel wie ich mir das vorstellen könnte:
1
//interrupt-Routine
2
TIMER0_OVF_vect:
3
// irgendein asm code
4
5
ldi     r18, 0b001
6
out     TCCR0B, r18
7
reti

Funktioniert das so oder sollte ich vor der Umstellung ein cli und 
danach ein sei einfügen (bzw. den Timer-Interrupt direkt aus- und wieder 
anschalten)? Ich habe zwar schon vieles gelesen aber über dieses Thema 
leider nichts gefunden. Über Lektüre würde ich mich natürlich auch 
freuen.

Schon mal vorab vielen Dank für die Unterstützung.

Grüße, Marco

von c-hater (Gast)


Lesenswert?

Marco G. schrieb:

> Ich würde gerne den Prescaler des Timer-Interrupts am Ende der
> Interrupt-Routine ändern. Ist dies ohne weiteres möglich?

Nein. Der Interrupt besitzt nämlich überhaupt keinen Prescaler.

Der Timer hingegen schon. Und dessen Prescalerfaktor darfst du natürlich 
jederzeit ändern.

Berücksichtigen mußt du allerdings, daß bei einer Änderung von einem 
geringen Faktor zu einem höheren nicht gewährleistet ist, daß der 
nächste Interrupt erst nach der zu erwartenden Zeit ausgelöst wird. Im 
schlimmsten Fall tritt er nämlich noch im Zyklus des geringeren Faktors 
auf.

Willst du diesen Effekt vermeiden, mußt du nicht nur den Prescalerfaktor 
setzen, sondern auch den Prescaler resetten. Auch dabei entsteht 
allerdings  ein Fehler, der bewegt sich aber immer unterhalb des Zyklus 
des kleineren Prescalerfaktors. Dafür tritt er aber immer auf, 
unabhängig davon, in welche Richtung der Faktor geändert wird.

Wenn man sich nicht mit speziellen Programmiertechniken auseinadersetzen 
möchte, mit denen man den Fehler komplett vermeiden kann, ist also die 
beste Vorgehensweise: beim Wechsel von einem niedrigen auf einen hohen 
Faktor: Prescaler-Reset, bei der umgekehrten Richtung: kein 
Prescaler-Reset.

von Marco G. (arccra)


Lesenswert?

Hallo c-hater,

astreine Antwort! Damit kann ich was anfangen. Ganz so Zeitkritisch ist 
die Anwendung nicht, also werde ich deine vorgeschlagene Lösung 
umsetzen.

Vielen Dank.

Grüße, Marco

von Michael Schurr (Gast)


Lesenswert?

Hi,

Im GTCCR das Bit 7 und danach das Bit 0 setzen. Damit bleibt der 
Prescaler im Reset festgenagelt (der Zähler steht dadurch ebenfalls) und 
kann auf ein anderes Teilverhältnis gesetzt werden. Den T/C dann 
ebenfalls explizit auf 0 setzen und anschliessend durch resetten von Bit 
7 im GTCCR den Prescaler wieder freigeben. Somit fangen PS und Timer 
beide exakt bei 0 den neuen Zyklus mit dem neuen Teilerverhältnis an....

von Spess53 (Gast)


Lesenswert?

Hi

>Im GTCCR das Bit 7 und danach das Bit 0 setzen. Damit bleibt der
>Prescaler im Reset festgenagelt (der Zähler steht dadurch ebenfalls) und
>kann auf ein anderes Teilverhältnis gesetzt werden.

Aber Vorsicht. Oft teilen sich zwei Timer einen Vorteiler. Bei diesem 
Vorgehen wird dann auch der andere Timer beeinflußt. Wenn ein Fehler von 
knapp einem Timertakt nicht stört kann man sich das ganze Prozedere 
sparen.

MfG Spess

von Peter D. (peda)


Lesenswert?

Es stellt sich allerdings auch die Frage nach der Sinnhaftigkeit einer 
solchen Aktion.

Wenn Du Dir mal die Programme von erfahrenen Programmierern ansiehst, 
dann stellen die den Prescaler einmalig in der Initialisierungsroutine 
auf den optimalen Wert und fassen ihn fürderhin nie mehr an.

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.