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
>Ich habe dabei an einen Timer Interrupt gedacht, stehe leider total auf >dem Schlauch und weis nicht wie ich das realisieren soll. So wie alle anderen vor dir auch: Datenblatt lesen und machen.
Vielen Dank für diesen Qualitativ hochwertigen Kommentar. :) Wie ich einen Timer Interrupt implementiere ist mir klar. Es geht mir um die Funktion mit dem Timeout, da habe ich keine Ahnung wie ich das am besten realisieren soll.
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
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
|
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.
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.