Hallo, ich auf meiner Applikation für einen 16 Bit Mikrocontroller einen Timeout realisieren bzw. implementieren und verwenden. Ich habe die Möglichkeit einen Timer zu starten und zu stoppen. An mehreren Codestellen möchte ich nun bei einem Fehlerfall bzw. nicht Ausführung von bestimmen Codestellen, dass der Timeout zuschlägt. Wie realisiert man prinzipiell so eine Timeout Funktionalität mit einem Timer ? Vielen Dank im Voraus!
> nicht Ausführung von bestimmen Codestellen, dass der Timeout zuschlägt. Was soll 'zuschlagen' konkret heißen? Wie sehen diese 'bestimmte Codestellen' aus? > Wie realisiert man prinzipiell so eine Timeout Funktionalität > mit einem Timer ? zb so, dass der Timer bei bestimmten Zählerständen oder Zählereignissen einen Interrupt auslöst. In der zugehörigen ISR kann man dann zb einen Zähler runterzählen solange der ungleich 0 ist. An der Aufrufstellt setzt man den Zähler auf einen Wert ungleich 0 und flechtet eine regelmässige Abfrage auf diesen Zähler in den Code, zb in Schleifen ein volatile uint8_t TimoutCounter; ISR( .... ) { if( TimeoutCounter > 0 ) TimeoutCounter--; } .... int main() { .... TimeoutCounter = 5; // maximal 5 Timer ISR AUfrufe Starte Timer; while( Ereignis nicht eingetroffen && TimeoutCounter != 0 ) { mach was warte } Stoppe Timer; if( TimeoutCounter == 0 ) { // zu spät. Das war ein Timeout } else { .... Das ist jetzt nur eine Variante. Es gibt noch unzählige andere Möglichkeiten, je nachdem welche Möglichkeiten du für den Timer hast, wie schnell der zählt, wie sich das Verhältnis von Timergeschwindigkeit zu Zeitdauer für den Timeout verhält, etc.
Na, den Timer einfach zählen lassen! Wenn alles sauber läuft, an den entsprechenden Stellen immer wieder auf '0' setzen. Am Hauptschleifenende prüfen, ob der kritische Wert überschritten wurde und das Programm reagieren lassen.
Danke für eure Vorschläge. Ich möchte allerdings einen Timeout in einem von mir geschriebenen Klasse einsetzen. In der Main While Schleife will ich nicht auf einen Timeout warten oder sonst irgendwas. Dies sollte alles in der Klasse funktionieren.
Leonhard schrieb: > Danke für eure Vorschläge. > > Ich möchte allerdings einen Timeout in einem von mir geschriebenen > Klasse einsetzen. In der Main While Schleife will ich nicht auf einen > Timeout warten oder sonst irgendwas. Dies sollte alles in der Klasse > funktionieren. Dann wäre zb eine Möglichkeit, dass du eine Callbackfunktion beim Timer registrierst, die in der ISR aufgerufen wird, wenn die Zeit abgelaufen ist. Das kann unter Umständen aber etwas tricky werden. Eine andere Möglichkeit wäre, wenn jede derartige Klasse der Hauptschleife eine Funktion zur Verfügung stellt, mit der Bitte, dass die von der Hauptschleife regelmässig aufgerufen werden soll, weil die Klasse dann ihre ausstehenden Timeouts durchcheckt. Denk dir was aus. Sei kreativ. In der Programmierung gibt es selten DAS eine Patentrezept mit dem man alles erschlagen kann. Aber es gibt Grundideen, Grundgedanken, die man in etwas angewandelter Form auf Problemstellungen loslassen kann. Solche Aufgabenstellungen schaffst du im realen Leben mit links, wenn du 8 verschiedene Aufgaben bearbeiten sollst und nur eine einzige Uhr zur Zeitkontrolle zur Verfügung hast.
Was ist denn ein Timeout? - Wenn man einem Programmteil eine bestimmte Zeit lässt, ein Ergebnis zu liefern. Wenn in dieser Zeit keine Reaktion erfolgt, dann will man was unternehmen. Wo das ist, spielt keine Rolle. Diese Funktionalität kann man genauso einer Klasse zuordnen: - Timer starten - kritische Funktion aufrufen - Timer auf '0' gezählt -> Ereignis auslösen -> kritische Funktion abbrechen Wie man das konkret implementieren kann, weißt nur du. Das kommt auf den Compiler an.
was ist denn die reaktion die du ausführen willst wenns mal länger dauert? ist es eine überwachung für den unwahrscheinlichen fall das es mal länger dauert, was aber eigentlich nicht passieren sollte. Oder ist das länger brauchen einer funktion, ein gewolltes ereigniss das du bewusst ausnutzen willst? ungewollt: watchdog verwenden gewollt: timer zurücksetzen/starten vor der funktion und interrupt enablen, danach wieder disablen soll es ohne interrupt funktionieren, dann kann dir wohl nur jemand helfen der deinen code kennt
Ich habe das ganze mal so implementiert:
1 | void OnTimeOut(void) // Zyklischer Timer, wird immer alle 10 ms ausgeführt |
2 | {
|
3 | if(FlagStartTimer == 1 && TimeOutCnt > 0) |
4 | TimeOutCnt--; |
5 | |
6 | if(FlagStartTimer == 1 && TimeOutCnt == 0) |
7 | {
|
8 | FlagStartTimer = 0; |
9 | |
10 | StoppTimer(); |
11 | }
|
12 | }
|
Timer starten:
1 | FlagStartTimer = 1; |
2 | TimeOutCnt = 50; // 10 ms * 50 = 500 ms |
Timer stoppen:
1 | FlagStartTimer = 0; |
Hallo Peter, danke für den Link. Was hat dies mit meinem Problem zu tun ?
Leonhard schrieb: > Hallo Peter, > > danke für den Link. Was hat dies mit meinem Problem zu tun ? Mit einem 'Multitask' System sind Timeouts relativ banal umzusetzen for( i = 0; i < 20 && !receivedCharacterFromUart(); i++ ) task_sleep( 10 ); ist zb ein banaler Timeout in einem Thread der auf Zeichen von der UART wartet. Dadurch dass in der Schleife die Rechenzeit immer wieder an andere Tasks abgegeben wird, können die weiterlaufen und nach der angegebenen Zeit (+- ein paar Zeiteinheiten) kriegt der Task wieder die Kontrolle um nachzusehen, ob an der UART etwas eingetrudelt ist. Wenn ja, hört er auf zu schleifen. Und wenn die Zeit (definiert durch die Anzahl der Schleifenwiederholungen mit der Sleep-Zeit) abgelaufen ist, ebenso. In einem Singletask System wäre das for( i = 0; i < 20 && !receivedCharacterFromUart(); i++ ) _delay_ms( 10 ); tödlich, da _delay_ms nur Zeit verbrutzelt. Aber das tut ja task_sleep nicht. Es wird zwar auch Zeit abgewartet, aber andere Tasks kriegen die Gelegenheit selbst wieder Arbeit zu machen.
Leonhard schrieb: > danke für den Link. Was hat dies mit meinem Problem zu tun ? Nun, Du stellst den Callback hinein, daß er nach dem Timeout zuschlägt. Und bist Du vor dem Timeout fertig, nimmst Du den Callback wieder raus. Peter
Folgende Angaben habe ich hier nicht erwähnt. Ich verwende kein Betriebssystem und somit habe ich auch keine Multitasking Funktionalität. Ich möchte in der neuen Klasse (objektorientierter Ansi C Code) eine Timeout-Funktionalität einbauen. Einen Timer kann ich aufsetzen und auch beenden. Ich hab noch Probleme, wie man geschickt dies Implementieren könnte.
Leonhard schrieb: > Ich verwende kein Betriebssystem und somit habe ich auch keine > Multitasking Funktionalität. Deswegen ja auch das 'Multitasking des kleinen Mannes' von Peter. Leonhard schrieb: > Ich möchte in der neuen Klasse (objektorientierter Ansi C Code) eine > Timeout-Funktionalität einbauen. Einen Timer kann ich aufsetzen und auch > beenden. Ich hab noch Probleme, wie man geschickt dies Implementieren > könnte. Das stand schon weiter oben. Du solltest jetzt mal gezielt die ansprechen, die dein Compilersystem kennen! Allgemein ist eigentlich alles gesagt.
Leonhard schrieb: > Ich möchte in der neuen Klasse (objektorientierter Ansi C Code) eine > Timeout-Funktionalität einbauen. Du soltest dir zu allererst einmal darüber klar werden, was du eigentlich willst. Wozu sollte ein "Timeout" dienen? Ich nehme mal an, daß du schlichtweg prozedural, also blockierend deine Programme schreibst: while (Ereignis noch nicht eingetreten) tu_nix_ausser_trampeln; Behandle_Ereignis(); Und da du dich mit sowas an jeder Ecke selber blockierst, suchst du nach einer Möglichkeit, aus solchen Blockaden herauszukommen - ohne zu begreifen, daß dies ein hausgemachtes Problem ist, das man mit einer anderen Programmierweise überhaupt nicht hat. Also: programmiere lieber ereignisorientiert: if (Ereignis eingetreten) Behandle_Ereignis(); if (was_anderes_gewesen) Reagiere_auf_das_Andere() if (nochwas) Tu_Nochwas() usw. immer im Kreise. Es ist schlichtweg die Ereignis-Loop. Das ist zugleich die Lösung für dein "Timeout-Problem", das du mit einem simplen systemweiten Uhrcounter erledigen kannst: Starte_eine_Aktion(); LetzterTermin = Uhrzeit + xxx Millisekunden; ... ... if (Ereignis eingetreten) { Behandle_Ereignis(); LetzterTermin = ungültig; } .... if (LetzterTermin < Uhrzeit) { Cancele_die_Aktion() LetzterTermin = ungültig; } .. kümmere_dich_um_andere_Ereignisse()... So etwa. Ich hoffe, du hast das gedankliche Prinzip herausgelesen. W.S.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.