Mikrocontroller Software - Hilfestellung für Timeout Implementierung

Gast #2603266
Lesenswert?

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!
#2603275
Lesenswert?

> 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.
Gast #2603285
Lesenswert?

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.
#2603292
Lesenswert?

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.
#2603308
Lesenswert?

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.
Gast #2603330
Lesenswert?

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
Gast #2603357
Lesenswert?

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;
#2603427
Lesenswert?

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.
Gast #2604423
Lesenswert?

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.
#2604460
Lesenswert?

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.
Gast #2605753
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren