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
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.
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++,
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...
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;
}
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.
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.
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.
Eine eigene Frage?
Dieser Thread ist über 9 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.