www.mikrocontroller.net

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


Autor: leif (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: leif (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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..

Autor: Werner B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: leif (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: leif (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: leif (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, jetzt hab ich's gerafft!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.