Ich habe in meinem Programm einen Wait Timer, der mit Hilfe von
Interrupts zählt.
1
voidvSetWaitTimer(UIuiWaitValue)
2
{
3
// initialize requested time
4
__disable_interrupt();// disable interrupt
5
guiWaitTimer=uiWaitValue;
6
__enable_interrupt();// enable interrupt
7
8
// wait until time is expired
9
while(guiWaitTimer>0)
10
{
11
// wait <-SCHLECHT?
12
}
13
}
Die gewünschte Zeit (in ms), die das Programm pausieren soll wird mit
der Variable uiWaitValue in die Funktion übergeben. Mein Problem ist
jedoch die Zeile mit dem "// wait", in der while-Schleife passiert
NICHTS, eine gefährliche Situation? Oder "darf" man das so realisieren?
Wie kann ich das vermeiden? Ich hatte an einen Scheduler im
Hauptprogramm gedacht, aber dann kann icht die Wartezeit nicht
universell per Funktion überall im Programm nutzen...
Weiß jemand Rat? Würde mich freuen.
Zugehöriger Interrupt:
1
#pragma vector=TIMER0_COMPA_vect
2
__interruptvoidTIMER0_COMPA_int(void)
3
{
4
if(guiWaitTimer>0)
5
{
6
guiWaitTimer--;// reduce counter every 1 ms
7
}
8
}
Prozessor: Atmel Atmega 328p
Compiler: IAR Embedded Workbench 5.5
Emitter schrieb:> in der while-Schleife passiert NICHTS, eine gefährliche Situation?
Was soll daran "gefährlich" sein?
Emitter schrieb:> Wie kann ich das vermeiden?
Mach doch einfach nebenbei was anderes bis der Timer "abgelaufen" ist.
Vielen Dank für die schnelle Antwort.
Läubi .. schrieb:> Emitter schrieb:>> in der while-Schleife passiert NICHTS, eine gefährliche Situation?>> Was soll daran "gefährlich" sein?
Ja, ich dachte mal gesagt bekommen zu haben, dass ich nicht "nichts" in
einer Schleife machen soll. Weil das Programm während der Wartezeit
quasi in der Endlosschleife hängt und im Fehlerfall, falls guiWaitTimer
vom Interrupt nicht korrekt auf Null herunter gezählt wurde, das
Programm sich komplett aufhängen würde, weil die Schleife dann niemals
verlassen werden kann.
Läubi .. schrieb:>> Mach doch einfach nebenbei was anderes bis der Timer "abgelaufen" ist.
Und "was anderes machen", ja mhh nur was?
Ich dachte nur man könnte das besser implementieren...
Achja, vergessen oben zu definieren:
Programmiersprache: C
Emitter schrieb:> Und "was anderes machen", ja mhh nur was?
Keine Ahnung... wenn es eh nix anderes zu tun gibt bringt
interruptgesteuertes Warten nur Komplexität aber keinen Nutzen.
Emitter schrieb:> Weil das Programm während der Wartezeit quasi in der Endlosschleife> hängt und im Fehlerfall,
Im Fehlerfall hilft es auch nicht irgendwas zu tun, du könntest
natürlich einen Timeout einbauen, das macht aber nur Sinn, wenn du auf
eine externes Signal wartest, ein Timeout bei einer Zeitwarteschleife
ist etwas unsinnig.
Wenn es nur darum geht zu warten könnte man ggf. den Timer per Vorteiler
langsamer laufen lassen und dann mit nur einem Interrupt auskommen. Die
Zeit ist dabei allerdings gerade mit dem 8 Bit Timer nicht so genau
einzustellen. Während des Wartens könnte man dann µC in einen
Stromsparmodus (z.B. Idel) versetzen.
Peter R. schrieb:> Wozu das Disable und Enable?>> In eine leere "Schleife" packe ich immer ein NOP. Ist aber nicht> notwendig.
Naja, um die globale Variable, welche im Interrupt dekrementiert wird,
zu beschreiben, muss natürlich der Interrupt pausiert werden, da ich
ansonsten nicht sauber reinschreiben kann. Deswegen zuerst disable
interrupt und dann wieder enable interrupt.
Emitter schrieb:> Ich dachte nur man könnte das besser implementieren...
Kommt auf die Situation an.
Ausser bei ganz kurzen Warteschleifen bzw. wenn das Programm ausser
Warten nichts zu tun hat, ist der ganze Ansazu mit Warten schon der
falsche Weg. Also faktisch gesehen, ist es fast immer der falsche Weg.
Ob jetzt mit Timer oder mit Prozessortakte verplempern (was im Grunde
dasselbe ist, nur die Basis ist eine andere)
Der saubere Ansatz besteht darin, zu realisieren, dass µC meistens mit
Eventsteuerung am einfachsten realisiert werden. In der Hauptschleife
werden alle möglichen Eventquellen nacheinander abgeklappert, ob der
Event eingetreten ist und wenn ja, wird er behandelt. Der Ablauf eines
Timers ist dann auch nichts anderes als ein Event.
In letzter Konsequenz bringt einen ein derartiges Vorgehen dann meistens
in die Richtung von Zustandsmaschinen.
Karl Heinz Buchegger schrieb:> Der saubere Ansatz besteht darin, zu realisieren, dass µC meistens mit> Eventsteuerung am einfachsten realisiert werden. In der Hauptschleife> werden alle möglichen Eventquellen nacheinander abgeklappert, ob der> Event eingetreten ist und wenn ja, wird er behandelt. Der Ablauf eines> Timers ist dann auch nichts anderes als ein Event.> In letzter Konsequenz bringt einen ein derartiges Vorgehen dann meistens> in die Richtung von Zustandsmaschinen.Falk Brunner schrieb:> Siehe Multitasking und statemachine
Danke für die Hilfe. Okay, also muss ich wie oben schon geahnt einen
Scheduler nutzen. Danke ;-)
Emitter schrieb:> Danke für die Hilfe. Okay, also muss ich wie oben schon geahnt einen> Scheduler nutzen. Danke ;-)
Das ist nicht weiter schlimm, du musst dich ja nicht an Windows oder
Linux orientieren.
Eine ganz einfache Möglichkeit ist eine main loop mit verschiedenen
Aufgaben
in der Art
Loop:
Call Task1
Call Task2
...
Jmp Loop
und wenn in Task2 ein Waittimer noch nicht abgelaufen ist tut sie eben
nichts. Der Timeinterrupt zählt einfach gesetzte Timer (z.B. einen für
jede Task) herunter auf 0, so braucht man nicht mal einen Event, die
Task wird halt wieder aktiv, wenn der Timer wieder auf 0 steht.
Allerdings muss man sich von dem einen linear durchlaufenden Programm
verabschieden, das mindeste ist die häppchenweise Aufteilung in Tasks,
die jeweils nur kurz laufen, z.B. prüfen ob ein Zeichen empfangen wurde.
Gruss Reinhard
Emitter schrieb:> Naja, um die globale Variable, welche im Interrupt dekrementiert wird,> zu beschreiben, muss natürlich der Interrupt pausiert werden, da ich> ansonsten nicht sauber reinschreiben kann. Deswegen zuerst disable> interrupt und dann wieder enable interrupt.
Ich löse das immer so, dass ich vorher dem Timer auf 0 setze. Da bleibt
dann genug Zeit die Variable zu setzen und der Timer läuft dann wirklich
genau die gewünschte Zeit.