Forum: Compiler & IDEs Timer: Wann OC Register initialisieren? Wie OCR erhöhen?


von leif (Gast)


Lesenswert?

Guten Abend,

ich hätte da mal zwei Fragen ;-)

OCR erhöhen:

so: OCR1A=TCNT1+78;
oder so: OCR1A=OCR1A+78;

Ist das zweite evtl. schneller, weil OCR1A schon 'da' ist?


Außerdem würde ich gerne wissen, wie ich die Dinger am besten
initialisiere, bei mir läuft nämlich der 16er erstmal durch, bevor es
einen Match/Interrupt gibt, der dann das OCR erhöht. Das soll so nicht
sein

Momentan in der Reihenfolge:

Prescaler
Interrupt Mask
OCR=0
sei()


sollte es andersherum sein, also erst sei()?

danke!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Ist das zweite evtl. schneller, weil OCR1A schon 'da' ist?

Nein, beide Register sind `volatile', d.h. sie werden immer
zugegriffen durch den Compiler.

von leif (Gast)


Lesenswert?

Hallo Jörg,

wenn ich mal Zeit habe, mich direkt mit Assembler zu befassen, und dem,
was der Compiler ausspuckt, muß ich solche Fragen vielleicht irgendwann
nicht mehr stellen :-)

Dann spiele ich jetzt wohl mal mit der Reihenfolge der
Initialisierung..

von Werner B. (Gast)


Lesenswert?

>so: OCR1A=TCNT1+78;
>oder so: OCR1A=OCR1A+78;

Das hängt davon ab was Du machen willst.
 Willst Du OCR1A vom aktuellen Zählerstand um 78 erhöhen (TCNT1 !=
OCR1A gilt ja die längste zeit), oder willst Du einfach nur OCR1A um 78
erhöhen?

>...läuft nämlich der 16er erstmal durch...
Das mit dem durchlaufen ist ist im datenblatt beschrieben.
Falls beim setzen von OCR1A der inhalt von TCNT1 schon größer oder
gleich dem neuen wert von OCR1A ist läuft der zähler erst einmal bis
TOP==MAX durch. IMHO ist OCR=0 quatsch da ich nicht logisch
nachvollziehen kann was dann der MATCH-interrupt im CTC mode macht. Das
entspricht in etwa einer 0/0 (NULL geteilt durch NULL), und das ist (ich
hoffe ich erinnere mich erinnere richtig) undefiniert.

mein vorschlag:

TCNT=0;
OCR=NichtNullWert;
Interrupt Mask;
sei();
Prescaler; // == starten des zählers

von Peter Dannegger (Gast)


Lesenswert?

In der initialisierung mach einfach:

OCR1A=TCNT1+78;


Im Interrupt mußt Du aber unbedingt:

OCR1A=OCR1A+78;

schreiben !

Es sei denn Du willst absichtlich den Interrupt total ungenau haben
(abhängig von anderen Interrupts und der Interrupteintrittszeit).


78 Zyklen ohne Vorteiler ist in C aber schon recht heftig, da könnte
Assembler nötig werden (nackter Interrupt ohne die Push/Pop-Arien).



Peter

von leif (Gast)


Lesenswert?

Hallo Werner,

was verschlägt einen denn um 5 hierher?! staun

Da ich OCR in der ISR (Match A) erhöhe, spielt es keine Rolle, was ich
mache. Im Augenblick, in dem der Befehl ausgeführt wird, ist ja eben
TCNT==OCR. Also zumindest in meinem Fall, dem Normal Mode (Match und
der Zähler läuft weiter durch).
Aber ich weiß jetzt nicht ob der Zähler nicht noch eine Weile läuft,
bis dieser Befehl ausgeführt wird, deswegen mag das erste u.U.
günstiger sein. Tiefere Timer-Materie :-)

Ich hab's gestern auch noch zum Laufen bekommen, der Zähler muß
einfach als letztes (nach sei();) gestartet werden.

Danke.

von leif (Gast)


Lesenswert?

Oh, guten Morgen Peter,

Vorteiler ist 256, deswegen hat der erste Zählerdurchlauf so lange
gebraucht, daß ich ewig nach einem nicht vorhandenen Fehler gesucht
habe..

> Es sei denn ..

Könntest Du das bitte noch ein bißchen erläutern, ich sehe den
Unterschied nicht.

von Peter Dannegger (Gast)


Lesenswert?

Nun, der Timer läuft weiter, das OCR aber nicht.

D.h. beim Addieren auf den Timer kriegst Du also immer mehr Verspätung
mit rein.


Beim Vorteiler 256 könnte es gut gehen, wenn nicht andere Interrupts
mehr als 256 Zyklen benötigen.

Trotzdem würde ich ein "sicher sein" einem "könnte gut gehen" immer
vorziehen.


Worst-Case Szenario:

Uart-Interrupt wertet gerade ein Kommando aus, danach kommt im Main
eine Teil unter Interruptsperre, dann drängelt sich noch ein externer
Interrupt vor. Und das alles darf nun nicht mehr als 256 Zyklen dauern
inklusive bis zur Addition im Timerinterrupt.


Peter

von leif (Gast)


Lesenswert?

Danke, jetzt hab ich's gerafft!

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.