Forum: Compiler & IDEs Timer-Überläufe handeln


von Switch (Gast)


Lesenswert?

Hallo!

Ich habe mal eine ganz grundlegende Frage zum Thema Timer.
Von einem Zeitpunkt 0 brauche ich mehrere Timer. Bei einem Takt von 1 
Mhz und 16 Bit Timer habe ich also eine Auflösung von 65.535ms. Wenn ich 
jetzt aber z.B. 550ms brauche, muss ich also die Überläufe zählen.

Jetzt weiß ich nicht, wie ich das am besten Implementieren soll.

Könnt hier mir einen Tipp geben?

Viele Grüße
Switch

von Klaus F. (kfalser)


Lesenswert?

Üblicherweise stellt man den Timer so ein, dass er einen Überlauf 
generiert mit einem günstigen Zeitintervall z.B. 1 ms oder 10 ms.
Dann zählt man die Überläufe, z.B. in dem der Timer bei jedem Überlauf 
einen Interrupt auslöst, und in der ISR wird ein Zähler hochgezählt.
Das Hauptprogramm wartet dann, bis der Zähler den gewünschten Stand hat.

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


Lesenswert?

Switch schrieb:

> Wenn ich
> jetzt aber z.B. 550ms brauche, muss ich also die Überläufe zählen.
>
> Jetzt weiß ich nicht, wie ich das am besten Implementieren soll.

Für bspw. einen AVR etwa so:
1
#include <stdint.h>
2
3
volatile uint16_t timer_overflow;
4
5
ISR(TIMER1_OVF_vect)
6
{
7
  timer_overflow++;
8
}

Nicht vergessen, dass Zugriffe auf timer_overflow aus dem main
thread nicht atomar sind!  Du musst also für einen Zugriff dort
die Interrupts blockieren, den Wert der Variablen lesen oder
vergleichen und danach die Interrupts wieder freigeben, andernfalls
ist nicht garantiert, dass low- und high-Byte von timer_overflow in
einem konsistenten Zustand gelesen werden.

Auf einer 32-bit-Architektur hättest du dieses Problem natürlich
nicht, da wäre ein 32bittiger Zugriff noch atomar.

von Switch (Gast)


Lesenswert?

Hallo!

Bei einem MSP sollte dann auch ein 16bit Zugriff atomat sein.

Das Problem ist, wenn sich Timer-Interrupts überlappen, den beim MSP 
haben die Timer B1 bis B7 den gleichen Interrupt-Vektor...
Wenn alle einen 10ms-Takt hätten würden ja alle zeitgleich kommen. Dann 
brauch ich aber bei einem 5 Überläufe der andere 11. Und was ist, wenn 
ich kein ganzzahliges Vielfaches von dem Timer habe. Z.B. 234ms, das 
wären ja dann 23 Überläufe + 4ms ....

von Peter D. (peda)


Lesenswert?

Switch schrieb:
> Bei einem MSP sollte dann auch ein 16bit Zugriff atomat sein.

Daher sollte man immer als erstes auch den CPU-Typ angeben.


Switch schrieb:
> Das Problem ist, wenn sich Timer-Interrupts überlappen, den beim MSP
> haben die Timer B1 bis B7 den gleichen Interrupt-Vektor...

Das ist ja doof.
Man hat oft Anwendungen mit mehreren Timern, wo einer sauschnell sein 
muß und nur wenig zu tun hat und andere viel machen müssen, aber 
seltener kommen.
Bei verschiedenen Vektoren kriegen beide unterschiedliche Prioritäten 
und kommen sich dann nicht in die Quere.

Aber bei nur einem Vektor - keine Ahnung, wie man das lösen kann.


Peter

von Switch (Gast)


Lesenswert?

Der Timer B0 hat einen eigenen Vektor mit einer höheren Priorität als B1 
bis B7.
Deswegen habe ich gedacht das ich den als Mastertakt nehme. Also das der 
dann 10ms Zyklus hat.
Aber dann habe ich das Problem, dass wenn ich ein ganzzahliges 
vielfaches habe, das der Timer B0 eher ausgeführt wird, als der 
eigentlich wichtige.

Das ist irgendwie alles nicht so einfach ...

von Klaus F. (kfalser)


Lesenswert?

Switch schrieb:
> Das Problem ist, wenn sich Timer-Interrupts überlappen, den beim MSP
> haben die Timer B1 bis B7 den gleichen Interrupt-Vektor...
> Wenn alle einen 10ms-Takt hätten würden ja alle zeitgleich kommen. Dann
> brauch ich aber bei einem 5 Überläufe der andere 11. Und was ist, wenn
> ich kein ganzzahliges Vielfaches von dem Timer habe. Z.B. 234ms, das
> wären ja dann 23 Überläufe + 4ms ....

Du kannst/solltest nicht für jede Wartezeit einen eigenen Timer 
spendieren!
Ein Timer mit z.B. 1 ms genügt, der zählt meinetwegen verschieden Zähler 
und im Hauptprogramm werden die einzelnen Aufgaben erledigt!

Nur für ganz zeitkritische Aufgaben die sich in kürzester Zeit erledigen 
lassen, kann man Timer mit eigenen ISRs aufsetzen.

von switch (Gast)


Lesenswert?

IMHO keine optimale Lösung. Da der zeitliche Ablauf von der Main-Loop 
abhängt. Wenn ein Timer "anschlägt" sollen auch gleich die Pins 
getoggelt werden. Am Besten mit Verzögerung t=0. Da das ja nicht geht, 
werde ich die Zeit messen, die der Controller vom Timer-Tick bis toggeln 
Pin benötigt und diese beim Setzen des Timers als Offset abziehen...

von Karl H. (kbuchegg)


Lesenswert?

switch schrieb:
> IMHO keine optimale Lösung.

'Optimal' gibt es in der Kirche.
Da darf man sich was wünschen.

> getoggelt werden. Am Besten mit Verzögerung t=0. Da das ja nicht geht,
> werde ich die Zeit messen, die der Controller vom Timer-Tick bis toggeln
> Pin benötigt und diese beim Setzen des Timers als Offset abziehen...

Welche Zeitvorgaben musst du denn einhalten?

PS: Wenns wirklich nur Pin-Toggeln ist ... das darf auch gerne in der 
ISR erledigt werden. Aber die meisten wollen ja erst mal 200 
quadratische Gleichungen lösen, das erste Buch Genesis über die UART 
ausgeben und auf dem Grafik-LCD soll ein Packman die Punkte wegfressen. 
Das ist dann schon zuviel, als das man es in der ISR erledigen kann.

Ändert nichts daran, dass man nur 1 Timer braucht.

von Switch (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> 'Optimal' gibt es in der Kirche.
>
> Da darf man sich was wünschen.

SWR nicht vergessen! - "Sie wünschen, wir spielen!" ;)

Karl heinz Buchegger schrieb:
> Welche Zeitvorgaben musst du denn einhalten?

Eine 1µs maximal 3µs Jitter.

Karl heinz Buchegger schrieb:
> PS: Wenns wirklich nur Pin-Toggeln ist ... das darf auch gerne in der
>
> ISR erledigt werden. Aber die meisten wollen ja erst mal 200
>
> quadratische Gleichungen lösen, das erste Buch Genesis über die UART
>
> ausgeben und auf dem Grafik-LCD soll ein Packman die Punkte wegfressen.
>
> Das ist dann schon zuviel, als das man es in der ISR erledigen kann.

Bin für die Bibel über den UART. Ok, die Bibel ist etwas stark 
komprimiert. Reden wir mal von 255 Bytes. Das begrenzt natürlich die 
Zeitspanne zwischen zwei Ticks. Mindestabstand 255 Bytes * 11 
Bits/Bytes/Datenrate + ein wenig Latenzzeit zum Betreten und Verlassen 
der ISR.

Damit ist aber auch das Thema "Zählen" der Überläufe und abhandeln der 
Timerzeiten mit einem Timer hinfällig...

von Peter D. (peda)


Lesenswert?

switch schrieb:
> Am Besten mit Verzögerung t=0. Da das ja nicht geht,

Warum geht das nicht?
Hat denn der MSP keine Output-Compare Funktion?

Bei den AVRs kann man die Compare-Ausgänge zyklusgenau (50ns) setzen, 
löschen oder togglen.


switch schrieb:
> werde ich die Zeit messen, die der Controller vom Timer-Tick bis toggeln
> Pin benötigt und diese beim Setzen des Timers als Offset abziehen...

Die Interruptlatenz kann man nicht so einfach abziehen, da sie nicht 
konstant ist (laufende Operation, andere Interrupts).


Peter

von Klaus F. (kfalser)


Lesenswert?

switch schrieb:
> Wenn ein Timer "anschlägt" sollen auch gleich die Pins
> getoggelt werden. Am Besten mit Verzögerung t=0.

So etwas geht manchmal schon.
Manche Timer haben dazu einen dedizierten Ausgang, der von der Hardware 
gleichzeitig gesetzt wird, wenn der Timer überläuft.
Bei längeren Zeiten muss man dann halt tricksen.
z.B. Wartezeit 250 ms:
Der Timer wird auf 10 ms Überlauf eingestellt.
In der ISR wird bis 24 gezählt, und beim 24. Mal wird der Ausgang 
aktiviert.
Beim 25. Mal Überlauf knallts dann.
Vorteil auch: Die Reaktionszeit der ISR ist nicht kritisch, man muss nur 
in den 10 ms zwischen 24. und 25. Überlauf den Pin aktivieren.
Aber das alles hängt von Deiner Hardware ab und man kann eben nur 
bestimmte Pins dazu verwenden.

von Switch (Gast)


Lesenswert?

Dei HW ist ein MSP430F2410. Das Problem ist glaub ich nicht den Pin zu 
toggeln, sondern -was ich zu Beginn etwas in den Hintergrund gelassen 
habe- die Daten über den UART zu versenden.

von Klaus F. (kfalser)


Lesenswert?

Switch schrieb:
> Dei HW ist ein MSP430F2410. Das Problem ist glaub ich nicht den Pin zu
> toggeln, sondern -was ich zu Beginn etwas in den Hintergrund gelassen
> habe- die Daten über den UART zu versenden.

Die Daten mit 1us genau über UART verschicken?

von Switch (Gast)


Lesenswert?

Genau. Timer Tick (t= x), Daten versenden (t = x +/- 3µs), Pin Toggeln 
(t = x +/- 3µs). x = Zeit in ms.

von Klaus F. (kfalser)


Lesenswert?

Switch schrieb:
> Daten versenden (t = x +/- 3µs)

Was soll das für einen Sinn haben?

von Switch (Gast)


Lesenswert?

Das ist die zulässige Genauigkeit.
Besser ist natürlich +/- 0. Und ob ein "-" Eintritt ist eine andere 
Sache.

von Peter D. (peda)


Lesenswert?

Welche Baudrate benutzt Du denn?
Kann Deine UART überhaupt auf 3µs genau starten?

Manche UARTs haben einen durchlaufenden Baudratenteiler und können nur 
auf ganze Bitzeiten starten, d.h. alle 104µs bei 9600Baud.


Peter

von Switch (Gast)


Lesenswert?

Wie soll ich das Verstehen.
Wenn mein Timer Tick eintritt, dann werden die Daten in den UART 
Sendepuffer verschoben.
Beim MSP befindet sich die UART Statemachine im IDLE-Mode. D.h. wenn ich 
mit meinem ersten Byte komme, wird es ausgetaktet.

Die Baudrate soll mindestens 500kBaud betragen. Je schneller, desto 
besser. ;)

von Peter D. (peda)


Lesenswert?

Switch schrieb:
> Wie soll ich das Verstehen.

Z.B. beim 8051 ist der Baudratenteiler durchlaufend.
Man schreibt in den Sendepuffer und dann kommt das Startbit mit der 
nächsten Flanke des Baudratenteilers. Wo der Baudratenteiler gerade 
steht, weiß man nicht.
Nach dem Senden eines Bytes folgt das nächste Byte also immer nach n * 
Bitzeit.

Ob das beim MSP auch so ist, sollte in dessen Datenblatt stehen.


Peter

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.