RS232 Timeout

OP #1702259
Lesenswert?
• ▲
▼
Hallo zusammen,
ich habe folgendes Problem:

Mein PIC kommuniziert über eine RS232 Schnittstelle mit einem 
Servo-Regler.
Der PIC sendet z.B. einen Abfragebefehl an den Regler, dieser Antwortet 
dann entsprechend.

 puts("Befehl"); //Übertrage Abfragebefehl
 gets(Antwort); //Empfange Antwort

Nun habe ich schon öfters das Problem gehabt das der PIC beim Empfangen 
stehen bleibt, da er auf eine Antwort
des Reglers wartet.
Da dieser zu diesem Zeitpunkt jedoch ausgeschalten oder noch nicht 
bereit war hatte er den Abfragebefehl auch nie erhalten.

Bisher hat das zwar funktioniert ist mir aber zu unsicher.

Nun möchte ich eine Funktion die z.B nach 50ms ohne Antwort vom Regler 
den Befehl erneut sendet.

Ich habe dabei an einen Timer Interrupt gedacht, stehe leider total auf 
dem Schlauch und weis nicht wie ich das realisieren soll.

Ich hoffe ihr könnt mir weiterhelfen.

Vielen Dank

Mfg Max
Gast #1702358
Lesenswert?
• ▲
▼
Hallo Max,

ich weiß nicht, wie dein gets(antwort) aussieht.
Oft ist es so, daß dort in einer WHILE-Schleife gewartet
wird bis ein Zeichen empfangen wurde.
Dies ist der Blockierer.

Du brauchst eine Schleife mit 2 Abbruchbedingungen:
- Zeichen (oder erwartete Zeichenzahl)
- Zeitzähler abgelaufen

Pseudo:
1
 Ende=0;
2
Zeitzähler=0;
3
while(!Ende){
4
  Zeitzähler++;
5
  if(Zeitzähler>Zeitgrenze)Ende=1;
6
  if (Zeichenda)Ende=2;
7
 }
8

9
if(Ende==2){
10
  // mach was mit empfangenen Daten
11
   }

Natürlich Zeitzähler anpassen, evtl. auch in/mit
Interrupt.

Hoffe das Prinzip ist klar ;)

avr
Gast #1702373
Lesenswert?
• ▲
▼
Angenommen, im Hintergrund läuft ein Timer, der Dir einen Sekundentakt 
vorgibt.
Angenommen, Du hast einen seriellen Empfangspuffer, der recvBuf heißt 
und der im seriellen Interrupt beschrieben wird, wobei der Index recvIdx 
mit jedem empfangenen Zeichen hochgezählt wird.

Dann etwa so:
1
volatile BYTE timer; // wird in Timer-ISR hochgezählt
2

3
timeout = timer + GewuenschterTimeoutInSekunden;
4

5
recvIdx = 0;
6

7
while((timer != timeout) && (recvIdx < AnzahlErwarteterZeichen));
8

9
// Daten auswerten
Gast #1702410
Lesenswert?
• ▲
▼
Hier habe ich noch eine etwas ausgearbeitetere Funktion, die auf eine 
bestimmte Zeichenkette wartet.
recvIdx wird bei Empfang eines Zeichens in der ISR hochgezählt.
recvBuf wird mit den empfangenen Zeichen in der ISR beschrieben.
timerCnt wird in der Timer-ISR hochgezählt.
i gibt an, bei welcher Position im Puffer mit dem Warten angefangen 
werden soll.
Es wird 0 zurückgegeben, wenn die erwartete Zeichenkette nicht empfangen 
wurde, oder der Index im Puffer, wo die erwartete Zeichenkette endet.
1
char SerialWaitFor(char* s, BYTE i)
2
{
3
  BYTE j, iMatch;
4
  BYTE   tmout; // = (timerCnt + (BYTE)TIMEOUT);
5

6
  j = iMatch = 0;
7
  tmout = (timerCnt + (BYTE)TIMEOUT);
8

9
  while(1)
10
  {
11
    if(recvBuf[i] == s[j])
12
    {
13
      if(j == 0)
14
      {
15
        iMatch = i;
16
      }
17
      j++;
18

19
      if(s[j] == 0)
20
      {
21
        return i;
22
      }
23

24
    }
25
    else
26
    {
27
      if (j != 0)
28
      {
29
        i = iMatch;
30
        j = 0;
31
      }
32
    }
33

34
    while(1)
35
    {
36
      if(i < (recvIdx-1))
37
      {
38
        i++;
39
        break;
40
      }
41

42
      if(timerCnt == tmout)
43
      {
44
        return 0;
45
      }
46
    } // while(1)
47
  } // while(1)
48
} // SerialWaitFor()

Man kann dann z.B. so etwas machen:
1
idx = SerialWaitFor("+CREG: 0,", 0);
2
if(idx)
3
{
4
  SerialWaitFor(",\"", idx);
5
  idx++;
6
  // answer message is \r\n+CREG: 0,1,"620A","26B5"\r\n\r\nOK\r\n
7
  //                           this ^ indicates the network state
8
  if((recvBuf[idx] == '1') || (recvBuf[idx] == '5'))
9
  {
10
    recvIdx = 0;
11
    return 1;
12
  }
13
}
Ausgewertet werden soll die Ziffer zwischen "+CREG: 0," und ",\"". Es 
wird also erst auf +CREG: 0, gewartet, dann von der Position idx 
ausgehend auf ," und dann ist klar, dass das Zeichen an idx+1 die 
gesuchte Ziffer ist.

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.