Forum: Mikrocontroller und Digitale Elektronik Timer_Tick()


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von hubert (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Guten Tag,
ich bin noch relativ neu in der Mikrocontroller Welt, und habe einen 
Frage.
Ich habe bis jetzt bei Zeitgeschichten in meiner Interrupt Routine 
(Zeitbasis von 1ms) immer Globale Variablen hoch oder runtergezählt und 
dann in der main bei erreichen der Zeit die entsprechende Aktion 
ausgeführt. Nun habe ich in einem Programm gesehen das dort in der 
Interrupt Routine die Funktion Timer_Tick aufgerufen wird. In dieser 
"Magischen Funktion" werden dann die Zeitsachen gemacht.
Ist dies die sauberer Lösung?

Wie sieht diese Funktion aller Wahrscheinlichkeit aus? Durfte diese 
Funktion nicht sehen:-(
Ist das eine Gängige Methode?

Lg Hubert

von Sebastian K. (sek)


Bewertung
0 lesenswert
nicht lesenswert
Das kann man so nicht sagen, ob das die sauberere Lösung ist. Da du den 
Sourcecode von Timer_Tick() nicht gesehen hast, vermute ich mal das die 
Funktion Bestandteil einer fertig compilierten Fremdbibliothek ist, 
vielleicht eines OS. Die Interrupt Routine fungiert in diesem Fall nur 
als Wrapper für Timer_Tick().

Eigene Zeitaufgaben kannst du natürlich direkt in die Interrupt Routine 
setzen. Das ist völlig egal. Da Timer_Tick() sowieso in den meisten 
Programmen nur einmal referenziert wird, wird der Compiler ohnehin den 
Code aus Timer_Tick() direkt in den Interrupt Handler einsetzen.

Worauf du achten solltest falls du den Systick Interrupt als Zeitgeber 
verwendest: Dieser hat in der Regel ein sehr hohe Priorität. Langer 
rechenintensiver Code ist hier tabu. Im Idealfall zählst du wirklich nur 
eine Timervariable hoch und machst den Rest dann außerhalb des Interrupt 
Handlers.

von B. P. (skorpionx)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
In dieser  Funktion (sehe das C Programm)generiere ich Zeit Flanken:
void InterruptLow(void) __interrupt 2

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
hubert schrieb:
> Ich habe bis jetzt bei Zeitgeschichten in meiner Interrupt Routine
> (Zeitbasis von 1ms) immer Globale Variablen hoch oder runtergezählt
Das ist ein No-Go. Stattdessen eine Variable (z.B. int SysTicker) 
hochzählen. Das gibt es teilweise sogar in der Hardware des Prozessors.

> Nun habe ich in einem Programm gesehen das dort in der
> Interrupt Routine die Funktion Timer_Tick aufgerufen wird. In dieser
> "Magischen Funktion" werden dann die Zeitsachen gemacht.

In einem preemptiven RTOS ist sowas z.B. ganz normal.

> Ist dies die sauberer Lösung?
dort noch mehr Variablen zu zählen eher nicht. Aber z.B. mit einem RTOS 
(das dieses Händling relativ effizient und allgemein umsetzt) oder für 
Dinge, die wirklch (fast) jede ms getan werden müssen (z.B. ADCs, Tasten 
oder Messages Pollen)

> Wie sieht diese Funktion aller Wahrscheinlichkeit aus?
Bei einem RTOS: Scheduler aufrufen,
Alle häufig zyklischen Dinge aufrufen (Tastatur, ADC, ...),
SysTicker++,

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Achim S. schrieb:
> hubert schrieb:
>> Ich habe bis jetzt bei Zeitgeschichten in meiner Interrupt Routine
>> (Zeitbasis von 1ms) immer Globale Variablen hoch oder runtergezählt
> Das ist ein No-Go. Stattdessen eine Variable (z.B. int SysTicker)
> hochzählen.
Und nur mit Zeitdifferenzen arbeiten.
Dann ist auch der Überlauf kein Problem mehr (siehe z.B. millis() beim 
Arduino: http://playground.arduino.cc/Learning/BlinkWithoutDelayDe)

> für Dinge, die wirklch (fast) jede ms getan werden müssen (z.B. ADCs,
> Tasten oder Messages Pollen)
Lustigerweise sind genau diese Beispiele Sachen, die nicht unbedingt 
exakt im ms Zeitraster passieren müssen und deshalb locker auch über 
ein Flag oder den ms-Zähler in der Haupschleife abgearbeitet werden 
könnten.
Wir packen das nur deshalb so gern in den Timerinterrupt, weil wir 
selber dieses "Uhrendenken" haben: Mittags um 12 geht es in die Kantine 
zum Essen. Dabei wäre es doch sinnvoller, dann zum Essen zu gehen, wenn 
wir Hunger haben...

: Bearbeitet durch Moderator
von Pandur S. (jetztnicht)


Bewertung
0 lesenswert
nicht lesenswert
Ich verwende jeweils einen timer Interrupt, der einiz reloadet, und das 
Timer-Came flag setzt. In der Main wird mit dem Timer-Came verzweigt und 
Sekundaere Zaehler gezaehlt.

Etwa :

interrupt timer {
 timercount= 192; // fuer 1ms oder so.
 timercame=1;
}

main () {

  ..

  loop
    if timercame==1 {
     ..
     timercame=0;
    }

von Thomas E. (picalic)


Bewertung
0 lesenswert
nicht lesenswert
Sapperlot W. schrieb:
> Ich verwende jeweils einen timer Interrupt, der einiz reloadet, und das
> Timer-Came flag setzt. In der Main wird mit dem Timer-Came verzweigt und
> Sekundaere Zaehler gezaehlt.

Halte ich allgemein für keine gute Idee.
1. ist die ISR auch nicht komplizierter, wenn sie bloß eine Variable 
hochzählt
2. Falls in der Main mal eine Aktion länger, als z.B. 1 ms dauert, geht 
die Uhr nach.
3. Da kannst Du Dir die ISR auch gleich sparen und in der Main das 
Hardware-Timerflag direkt auswerten und ggf. rücksetzen, statt ein 
Software-Timerflag einzuführen.

: Bearbeitet durch User
von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Thomas E. schrieb:
> Halte ich allgemein für keine gute Idee.
Korrekt: wenn die Hauptschleife mal länger als 1ms dauert, dann geht auf 
diese Weise Zeit verloren. Ein Flag setzen und wieder zurücksetzen ist 
so ähnlich wie ein sättigender 1-Bit-Zähler, der in der ISR hoch- und in 
der Hauptschleife heruntergezählt wird.
Durch das explizite Setzen und Zurücksetzen ist lediglich das 
Semaphorenproblem umgangen...

Fazit: die sicherste Methode ist, nur in der ISR hochzuzählen, und in 
der Hauptschleife nur zu lesen.

von A. S. (achs)


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Lustigerweise sind genau diese Beispiele Sachen, die nicht unbedingt
> exakt im ms Zeitraster passieren müssen und deshalb locker auch über ein
> Flag oder den ms-Zähler in der Haupschleife abgearbeitet werden könnten.

Stimmt. Meine Beispiele machen nur dann Sinn, wenn die hauptschleife 
(manchmal) deutlich über 10ms liegt. Und die Kosten separater Interrupts 
hoch sind.

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]
  • [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.