Forum: Compiler & IDEs Zeichen über USART empfangen


von jens67 (Gast)


Lesenswert?

Hallo!

Ich habe ein programmiertechnisches Problem in C:

Ich möchte Befehle, welche über USB an einen mC kommen, auslesen und 
auswerten, da sie dann über RS 485 an weitere Geräte geschickt werden. 
Hierzu habe ich folgende Abfrage-Routine:
1
        i = 0;
2
      while (i < NUM_BYTES) 
3
      {
4
          if (USART_RXBufferData_Available(&USART_data)) 
5
          {
6
        receiveArray[i] = USART_RXBuffer_GetByte(&USART_data);
7
        if (receiveArray[i] == 'Q')
8
        {
9
          break;
10
        }
11
        else
12
          i++;
13
      }
14
    }

NUM_BYTES bezeichnet die Anzahl der einzulesenden Bytes (Also die Länge 
des Befehls). Nun möchte ich unterschiedlich lange Befehle einlesen, 
welche jeweils mit einem Zeichen (z.B Q) terminiert werden. Wird dieses 
Zeichen als i-tes Element eingelesen, soll der Einlesevorgang beendet 
werden.
Das Einlesenen habe ich mit obiger if-Abfrage realisiert.

Der Befehl soll dann weitergesendet werden:
1
      i=0;
2
      while (i<NUM_BYTES)
3
      {
4
        bool byteToBuffer;
5
        byteToBuffer = USART_TXBuffer_PutByte(&USART_485_data, receiveArray[i]);
6
        
7
        if(byteToBuffer)
8
            {
9
          i++;
10
        }
11
      }

Dss Problem ist nun, wenn ich z.B. einen Befehl mit 4 Bytes ('ABQS') 
sende, dann wird zwar beim ersten Mal nur 'ABQ' weitergesendet, beim 
nächsten Befehl allerdings wird das 'S' aus dem Puffer dem Befehl 
vorangestellt (also z.B. 'SABQ').
Hat hier jemand einen Tipp wie ich das lösen kann?

von Ralf (Gast)


Lesenswert?

jens67 schrieb:
> Hat hier jemand einen Tipp wie ich das lösen kann?
Puffer leeren?

von jens67 (Gast)


Lesenswert?

Und wie gehe ich da vor?

von Karl H. (kbuchegg)


Lesenswert?

Das widerspricht sich:

> Nun möchte ich unterschiedlich lange Befehle einlesen,
> welche jeweils mit einem Zeichen (z.B Q) terminiert werden.

und

> wenn ich z.B. einen Befehl mit 4 Bytes ('ABQS') sende

Der Befehl ABQS kann laut deiner vorhergehenden Definition keine 4 Bytes 
haben.



Wenn deine Befehle keine einheitliche LÄnge mehr haben, dann wird wohl 
das hier
1
      while (i<NUM_BYTES)

nicht mehr sinnvoll sein. Denn ein einzelner Befehl ist nun mal jetzt 
keine NUM_BYTES Zeichen mehr lang.

Dein Befehl hört mit einem 'Q' auf. Also wird wohl dieses 'Q' irgendwo 
in der Abbruchbedingung der Schleife vorkommen müssen. (Die Schleife ist 
an dieser Stelle sowieso meistens eine ganz schlechte Idee)

von Matthias L. (Gast)


Lesenswert?

>ss Problem ist nun, wenn ich z.B. einen Befehl mit 4 Bytes ('ABQS')
>sende, dann wird zwar beim ersten Mal nur 'ABQ' weitergesendet, beim
>nächsten Befehl allerdings wird das 'S' aus dem Puffer dem Befehl
>vorangestellt (also z.B. 'SABQ').
>Hat hier jemand einen Tipp wie ich das lösen kann?


Ich würde zuerst zum Übertragungsprotokoll ein Timeout definifieren.
zB: die Zeitdauer, die die Übertragung von fünf Bytes dauert.

Wenn jetzt zB folgendes empfangen wird:
ABCQE (hier eine Pause größer oben beschrieben) SDFQ ...

so wird empfangen:
ABCQ => Auswerten,
E dann Timeout => ignorieren, da gegen PRotokoll (Q) verstößt,
SDFQ => Auswerten,

..

von jens67 (Gast)


Lesenswert?

Gibt es denn keine Möglichkeit, einfach den Buffer zu leeren, nachdem 
z.B. 'Q' eingelesen und in das ReceiveArray gespeichert wurde?

von Ralf (Gast)


Lesenswert?

Doch!
1
uint8_t *p=Puffer;
2
uint8_t i=lenPuffer;
3
while(i--)
4
 *p++=0;
oder:
1
for (uint8_t i=0; i < lenPuffer; i++)
2
 Puffer[i]=0;
manchmal reicht es auch (bei dir sollte es gehen), den Schreib-/ 
Lesezeiger nur wieder auf den Anfang zu setzen.

von jens67 (Gast)


Lesenswert?

Danke, Ralf.

Aber ich blick noch nicht so ganz durch, was in meinem Fall der Puffer 
ist bzw. wie ich die Pointer wieder auf den Anfang setze...

von Ralf (Gast)


Lesenswert?

jens67 schrieb:
> was in meinem Fall der Puffer ist
Das verstehe ich nun wieder nicht. Du musst doch mal eine Variable 
deklariert haben, die dazu da ist, die empfangenen Zeichen aufzunehmen?

von jonas biensack (Gast)


Lesenswert?

Das Thema Pointer solltest du dir bei einer schönen Tasse Kaffee und 
Kuchen bei einem Sauwetter wie heute zu Gemüte führen und dann nochmal 
und nochmal und...

Mit einfachen Beispielen anfangen. Pointer auf Anfang vom Array? Das ist 
doch schon fast der Fall schlecht hin :)
Also:

uint8_t EinByte; // Ich bin ein Byte
uint8_t EinArrayOfBytes[]; // Ich hab mehrere Bytes

uint8_t *EinByte_P; // Ich bin ein Zeiger auf ein Byte, zeige aber noch
// auf nichts


EinByte = EinArrayOfBytes; // Nun zeige ich auf das erste Element im 
Array
// So kann ich zum Beispiel einer Funktion übergeben werden, ohne dass 
das
// komplette Array kopiert werden muss.

Wenn noch Fragen?

gruß Jonas

von jens67 (Gast)


Lesenswert?

Danke, war jetzt komplett daneben, funktioniert nun. ;-)

Eine Frage hätt ich aber noch: Wenn in nun die Zeichen eingelesen habe, 
habe ich ja ein Array mit i Elementen. Wenn ich nun die Zeichen durch 
logische Operatoren vergleichen möchte, muss ich ja immer a la
1
if (receiveArray[0] == 'A' && receiveArray[1] == 'B') usw.
vorgehen.
Kann ich dieses Array in z.B. einen String umwandeln, sodass ich einfach 
z.B.
1
if (receive == 'AB') usw.
verwenden kann?

von jonas biensack (Gast)


Lesenswert?

Praktisch wär das, aber ich wüsste jetzt nicht wie?!  - ehm duck und 
weg...

von Helfer (Gast)


Lesenswert?

In der Standardlibrary gibt's dazu die Funktionen strcmp & Co. RTFM. :)

von Karl H. (kbuchegg)


Lesenswert?

Und damit sind wir (wieder mal) beim Standard-Problem:

Du brauchst ein C-Lehrbuch um die Sprache zu lernen, ehe du dich dann an 
µC-Programmierung wagst.

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
Noch kein Account? Hier anmelden.