Forum: Mikrocontroller und Digitale Elektronik AVR: Timer und OCR "gegeneinander" laufen lassen?


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


Lesenswert?

Hi zusammen,

ich plane folgendes zu machen: Timer 1 mit Output Compare (wo der 
Interrupt wichtig ist) läuft und macht. Initialisiert wir der OC idR mit 
65535, also dem maximalwert.

Ein weiterer Timer ermittelt die aktuell notwendige Frequenz und möchte 
die OCR1 modifizieren.

Natürlich besteht nun das Risiko, dass ich einen neuen OCR-Wert für 
Timer1 schreibe, wo der Timer schon darüber weg ist, und ich "ewig" 
warte bis der Interrupt kommt (weil er erstmal eine Ehrenrunde drehen 
muss)

Soweit ich das Datenblatt verstehe, kommt der OutputCompare-Interrupt 
nur bei Übereinstimmung, es erfolgt keine Prüfung "größer gleich". 
Verstehe ich das richtig?

Ich kann natürlich in der ISR auf den momentanen Wert des timers prüfen, 
und mit Sicherheitsabstand setzen. Ganz wohl fühl ich mich dabei 
nicht...

Die "Mädchen-Variante" wäre auch, einfach den OCR-Wert bis zum neuen 
Sollwert sequenziell erniedrigen, dann wird inzwischen wohl ein 
interrupt ausgelöst... aber von 65535 auf z.B. 1234 runterzählen 
verbraucht ja sinnlose Takte...


Was mein ihr?

von Karl H. (kbuchegg)


Lesenswert?

Michael Reinelt schrieb:

Zunächst mal:
Welchen Timer Modus benutzt du?


Es gibt einige Modi, die sich selbst um dieses 'Problem' kümmern, in dem 
sie den Update des OCR Registers Double Buffern und das eigentliche OCR 
Register bei Erreichen des Top-Wertes updaten.


PS: Nur weil ein Timer-Modus 'Fast-PWM heißt', bedeutet das nicht, dass 
man damit auch eine PWM erzeugen muss.


Da du eine Frequenzerzeugung angesprochen hast, würde ich sogar eher 
dahingehend tendieren, dass ev. der CTC MOdus für dich das richtige ist. 
Auch dort erfolgt der Update des OCR Registers erst bei Erreichen des 
Top-Wertes.

> Soweit ich das Datenblatt verstehe, kommt der OutputCompare-Interrupt
> nur bei Übereinstimmung, es erfolgt keine Prüfung "größer gleich".
> Verstehe ich das richtig?

Das verstehst du grundsätzlich richtig.

> Was mein ihr?

Such dir einen Timer-MOdus, der dieses 'Problem' für dich löst.

von Bronco (Gast)


Lesenswert?

Ist eigentlich ganz einfach:
Sofern es die Hardware nicht eh schon für Dich macht, beschreibe das 
OCR1 einfach im entsprechenden Nulldurchgang-Interrupt.

Es früher die Standard-Methode, um glitch-freies Umschalten zu erzeugen: 
die Register immer nur bei Null-Durchgang (i.a.R. der 
Timer-Overflow-Interrupt) beschreiben.

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


Lesenswert?

Karl Heinz Buchegger schrieb:
> Welchen Timer Modus benutzt du?

CTC

> Es gibt einige Modi, die sich selbst um dieses 'Problem' kümmern, in dem
> sie den Update des OCR Registers Double Buffern und das eigentliche OCR
> Register bei Erreichen des Top-Wertes updaten.
Ja, hab ich grad nachgelesen. bei CTC ist dieses double-buffering aber 
nicht aktiv.


> Da du eine Frequenzerzeugung angesprochen hast, würde ich sogar eher
> dahingehend tendieren, dass ev. der CTC Modus für dich das richtige ist.
> Auch dort erfolgt der Update des OCR Registers erst bei Erreichen des
> Top-Wertes.

nein, eigentlich nicht.

ich fürchte ich hab mich etwas undeutlich ausgedrückt, was meine 
Anforderung angeht:

Timer 1 erzeugt ein Clock-Signal für einen Schrittmotor, die Frequenz 
wird per CTC gesteuert. Das alleine funktioniert problemlos.

parallel wird über Timer0 die Beschleunigungs (oder Brems-) Rampe 
generiert, indem in regelmäßigen kostanten Abständen die 
Soll-Geschwindigkeit erhöht bzw. erniedrigt wird.

Wir beginnen mit der niedrigsten Geschwindigkeit: CTC wird auf den 
maximalwert 65535 gesetzt, und Timer 1 beginnt zu zählen: 0, 1, 2...

in der Zwischenzeit kommt ein Interrupt von Timer 0 und erhöht die 
Geschwindigkeit, der neue Sollwert von z.B. 30.000 wird in das 
OCR1A-Register geschrieben. timer 1 zählt brav weiter (angenommen er 
wäre so bei 500) wird aber nicht mehr bis 65535 zählen sondern nur mehr 
bis 30000. Dieses Spiel kann sich nun mehrfach wiederholen.

Kritisch wirds nun wenn sich der neue CTC-Wert und der momentane 
Zählerstand begegnen: Angenommen Timer 1 wäre bei 5000, CTC steht 
momentan bei 6000 und wird aber auf 4000 reduziert. Damit hat der 
CTC-Wert den Zählerstand "überholt", Interrupt wird keiner ausgelöst, 
Timer 1 zählt durch bis 65535, geht auf 0 und dann weiter bis 4000. Das 
meine ich mit "Ehrenrunde".

Ich müsste also, bevor ich den neuen CTC-Wert schreibe, prüfen ob nicht 
der Zählerstand schon höher ist. Wenn ja, entweder den CTC auf den 
momentanen Zählerstand + etwas Reserve setzen, oder den Zähler selbst 
auf etwas unter CTC. In jedem Fall soll möglichst sofort ein Interrupt 
ausgelöst werden.

Unsicher bin ich auch deswegen, weil während lesen und verarbeiten des 
Zählerstandes dieser sich intern ja schon weiterentwickelt haben kann.

ich hoffe ich konnte nun klarer erklären worauf ich hinaus will....



lg Michi

von Rolf M. (rmagnus)


Lesenswert?

Michael Reinelt schrieb:
> Unsicher bin ich auch deswegen, weil während lesen und verarbeiten des
> Zählerstandes dieser sich intern ja schon weiterentwickelt haben kann.

Das tut er allerdings nicht völlig unvorhersehbar.

Michael Reinelt schrieb:
>> Da du eine Frequenzerzeugung angesprochen hast, würde ich sogar eher
>> dahingehend tendieren, dass ev. der CTC Modus für dich das richtige ist.
>> Auch dort erfolgt der Update des OCR Registers erst bei Erreichen des
>> Top-Wertes.
>
> nein, eigentlich nicht.

Richtig. Das Datenblatt merkt aber auch gleich an, wie die Alternative 
aussieht:

**********************************************************************
However, changing the TOP to a value close to BOTTOM when the counter is
running with none or a low prescaler value must be done with care since 
the CTC mode does not have the double buffering feature. If the new 
value written to OCR1A or ICR1 is lower than the current value of TCNT1, 
the counter will miss the compare match. The counter will then have to 
count to its maximum value (0xFFFF) and wrap around starting at 0x0000 
before the compare match can occur.
In many cases this feature is not desirable. An alternative will then be 
to use the fast PWM mode using OCR1A for defining TOP (WGM13:0 = 15) 
since the OCR1A then will be double buffered.
**********************************************************************

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


Lesenswert?

Rolf Magnus schrieb:
> **********************************************************************
> However, changing the TOP to a value close to BOTTOM when the counter is
> running with none or a low prescaler value must be done with care since
> the CTC mode does not have the double buffering feature. If the new
> value written to OCR1A or ICR1 is lower than the current value of TCNT1,
> the counter will miss the compare match. The counter will then have to
> count to its maximum value (0xFFFF) and wrap around starting at 0x0000
> before the compare match can occur.
> In many cases this feature is not desirable. An alternative will then be
> to use the fast PWM mode using OCR1A for defining TOP (WGM13:0 = 15)
> since the OCR1A then will be double buffered.
> **********************************************************************

Ich glaube aber das ist nciht das was ich möchte: In dem Fall würde der 
Timer 1 immer den ersten gesetzten Wert erreichen. Solange die noch 
weit voneinander entfernt sind, möchte ich ja dass das intervall 
verkürzt wird.

beispiel: Zählerstand = 10, OCR1A = 65535. jetzt kommt meine rampe ins 
Spiel, und setzt OCR1A auf 20000. Jetzt soll der Timer wirklich bei 
20000 überlaufen 8und nciht die ganze erste Runde bis 65535 durchzählen)

von Rolf M. (rmagnus)


Lesenswert?

Michael Reinelt schrieb:
> beispiel: Zählerstand = 10, OCR1A = 65535. jetzt kommt meine rampe ins
> Spiel, und setzt OCR1A auf 20000. Jetzt soll der Timer wirklich bei
> 20000 überlaufen 8und nciht die ganze erste Runde bis 65535 durchzählen)

Wenn das bei einem Zählerwert von 20010 passiert, wäre das auch nicht 
anders. Ist es in dem Fall egal?
Du kannst eben nicht alles haben. Entweder hast du double buffering, 
dann mußt du immer bis zum nächsten Zyklus warten, bis der Wert aktiv 
wird, oder du nutzt einen Modus ohne double buffering, dann hast du halt 
das bekannte Problem, daß dein OCR-Wert evtl. über den Timer-Wert 
springt und dann der Timer bis ganz oben läuft. Was soll in diesem Fall 
denn überhaupt passieren? Der Timer kann ja nicht in der Zeit 
zurückspringen und den neuen OCR-Wert übernehmen, bevor du ihn 
eingetragen hast. In dem Fall muß der Timer also eh erstmal noch eine 
Runde drehen.
Ansonsten mußt du es halt so ähnlich machen, wie Bronco geschrieben hat, 
also den OCR-Wert nur dann ändern, wenn der Timer wieder bei 0 anfängt, 
also im Compare-Match-Interrupt.

von Peter D. (peda)


Lesenswert?

Nimm doch einen der gepufferten PWM-Modi.
Man kann auch bei denen Interrupts ausführen und man muß auch nicht 
einen Pin als PWM-Ausgang schalten.

Eine andere Methode, man hält den Reloadwert in einer Variable und 
addiert ihn dann im Compareinterrupt als nächstes Compare.
Der Timer läuft durch und man kann sogar mit dem Compare-B eine völlig 
andere Frequenz erzeugen.

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.