Forum: Compiler & IDEs Speichern von UART Daten


von Eberhard (Gast)


Lesenswert?

Hallo zusammen,

ich möchte Daten die ich über den UART gesendet bekomme in Variablen 
speichern.
Die Daten die gesendet werden sind unterschiedlich lang (max. 10Zeichen) 
und ich weiß nicht direkt was gesendet wird, bis auf das es insgesamt 6 
Datenpakete sind. Zusammengefasst 10 Zeichen sind und 6 Pakete, jedoch 
nicht was in den Paketen steht.

Einmal hatte ich die Idee mit einem Mehrdimensionalen Array[11][7].
Oder mit einem Scruct.

Mein Problem ist, dass ich nicht auf den Trichter kommen, wie ich die 
Daten abspeichern soll, also wie ich die Daten in ein Scruct speicher...

typedef struct Data
{
  char  ch_data_name_one;
  char  ch_data_page_one;

  char  ch_data_name_secound;
  char  ch_data_page_secound;

  char  ch_data_name_third;
  char  ch_data_page_third;
}S_Data;

S_Data g_SData;


Grüße

von Karl H. (kbuchegg)


Lesenswert?

Eberhard schrieb:

> Die Daten die gesendet werden sind unterschiedlich lang (max. 10Zeichen)
> und ich weiß nicht direkt was gesendet wird, bis auf das es insgesamt 6
> Datenpakete sind.

Das ist dein erster Problemkreis.

'Ich weiß nicht' geht schon mal gar nicht. Ein µC ist kein Hellseher, du 
genausowenig.
D.h. der Sender muss Steuerinformation mitschicken, mit der er zb 
ausdrückt: Jetzt kommt der "Name" und das sind zb 4 Zeichen (oder: jetzt 
kommt der "Name" und ich schicke dir dann die Zeichen, wobei ich den 
Text mit einem vereinbarten Ende-Kennzeichen abschliesse)

> Einmal hatte ich die Idee mit einem Mehrdimensionalen Array[11][7].
> Oder mit einem Scruct.

Kann man beides machen.
In deinem Fall ist ein struct wahrscheinlich schöner.

> Mein Problem ist, dass ich nicht auf den Trichter kommen, wie ich die
> Daten abspeichern soll, also wie ich die Daten in ein Scruct speicher...

Wenn du die Steuerinformation empfängst, weißt du was als nächstes 
kommt. Die Steuerinformation wird selbst wieder in Variablen gespeichert 
und beim Empfang des nächsten Zeichens kann man dann mit dieser 
Steuerinformation entscheiden, wo das gerade empfangene Zeichen 
hingehört.

von Eberhard (Gast)


Lesenswert?

Verdammt sorry, diese Information hatte ich außer acht gelassen!

Der Abschluss ist 0x17 = ASCII --> END OF TRANSMISSION

von Karl H. (kbuchegg)


Lesenswert?

Eberhard schrieb:
> Verdammt sorry, diese Information hatte ich außer acht gelassen!
>
> Der Abschluss ist 0x17 = ASCII --> END OF TRANSMISSION

Schön.
Trotzdem brauchst du noch eine 'Einleitung' mit der du dem Empfänger 
mitteilst, was als nächstes kommt.
Du musst aus dem Status
> 6 Pakete, jedoch nicht was in den Paketen steht.
raus.
Ich weiß nicht was in einem Paket drinnen ist, geht nicht. Da muss der 
Sender eben am Anfang eines Paketes mitteilen: Jetzt kommt der Name, das 
nächste Paket enthält die Kontonummer, etc. etc.

von Eberhard (Gast)


Lesenswert?

1
void get_data(void)
2
{
3
  uint8_t un8_all_data_count = 0;
4
  uint8_t un8_colum_count = 0;
5
  uint8_t un8_raw_count = 0;
6
  char ch_data[12][6];
7
  
8
  while (s_CmdBuffer[un8_all_data_count+1] != '\0')                    
9
  {
10
    if (s_CmdBuffer[un8_all_data_count+1] == 0x16)                     
11
    {
12
      ch_data[un8_colum_count][un8_raw_count] = '\0';                   
13
      un8_colum_count = 0;
14
      un8_raw_count ++;                                 
15
      un8_all_data_count ++;                                
16
    }
17
    else
18
    {
19
      ch_data[un8_colum_count][un8_raw_count] =    
20
      s_CmdBuffer[un8_all_data_count+1]; 
21
    
22
      un8_colum_count ++;                                 
23
      un8_all_data_count ++;                               
24
    }
25
  }
26
}

von Karl H. (kbuchegg)


Lesenswert?

> char ch_data[12][6];

Das sind 12 Zeilen mit je 6 Spalten.
D.h. du hast 12 Strings, wobei jeder String aus 6 Bytes bestehen kann.

(Merkregel: der letzte Index läuft am schnellsten)

Zum Rest: Du bist sicher, dass dein s_CmdBuffer bereits alle Zeichen 
aller 6 Pakete beinhaltet, wenn diese Funktion aufgerufen wird?

von Flash Gordon (Gast)


Lesenswert?

Ich wuerd einen Ringbuffer verwenden und mir in einem Array pointer, 
resp indices, in den Ringbuffer hinein halten, die auf den jeweiligen 
Anfang einer Meldung zeigen.

von Karl H. (kbuchegg)


Lesenswert?

> Mein Problem ist, dass ich nicht auf den Trichter kommen, wie ich
> die Daten abspeichern soll, also wie ich die Daten in ein Scruct
> speicher...

Das geht dann zb mit einer Hilfsfunktion, die den nächsten String aus 
dem 'Input' rausholt und in die Stringvariable deiner Wahl umkopiert
1
typedef struct Data
2
{
3
  char ch_data_name_one[12];
4
  char ch_data_page_one[12];
5
  char ch_data_name_secound[12];
6
  char ch_data_page_secound[12];
7
  char ch_data_name_third[12];
8
  char ch_data_page_third[12];
9
}S_Data;
10
S_Data g_SData;
11
12
uint8_t NextString( char* target, char* source, uint8_t index )
13
{
14
  while (source[index] != '\0' &&
15
         source[index] != 0x16)
16
  {
17
    *target = source[index]
18
    target++;
19
    index++;
20
  }
21
22
  *target = '\0';
23
  if(source[index] != '\0')                   
24
    index++;
25
26
  return index;
27
}
28
29
void get_data(void)
30
{
31
  uint8_t index = 0;
32
33
  index = NextString( g_SData.ch_data_name_one, s_CmdBuffer, index );
34
  index = NextString( g_SData.ch_data_page_one, s_CmdBuffer, index );
35
  index = NextString( g_SData.ch_data_name_secound, s_CmdBuffer, index );
36
  index = NextString( g_SData.ch_data_page_secound, s_CmdBuffer, index );
37
  index = NextString( g_SData.ch_data_name_third, s_CmdBuffer, index );
38
  index = NextString( g_SData.ch_data_page_third, s_CmdBuffer, index );
39
}

von Rush (Gast)


Lesenswert?

Komplizierter geht es wirklich nicht mehr....
Warum machst Du die Prüfung auf Start- und Endzeichen nicht in der 
Interrupt-Routine und setzt Dir ein Flag wenn alles im Empfangspuffer 
ist.
D.h., das Start- und Endzeichen brauchst Du nicht im Datenpuffer 
eintragen.
Beispielsweise so:
1
uart_interrupt_rx()
2
{
3
4
   unsigned char c;
5
6
   c = uart_rx_register;
7
8
   switch(c){
9
10
   case STARTSIGN:  bufferpointer = cmdbuffer;
11
                    buffer_set_flag = 0;
12
                    break;
13
   case STOPSIGN:   buffer_set_flag = 1;
14
                   break;
15
16
   default:
17
                   bufferpointer++ = c;
18
   }
19
}

Da fehlt noch einiges, aber grundsätzlich mache ich das immer SO.

von Eberhard (Gast)


Lesenswert?

Erstmal vielen Dank für die Beispiele  Hilfe  Anreize!

Karl Heinz Buchegger schrieb:
> while (source[index] != '\0' &&
>          source[index] != 0x16)

Momentan ist es so, dass ich weiß, nach einem 0x16 ist der ersten 
Datensatz fertig und der nächste kommt dran, hier wird geprüft ob ein 
0x16 und ein \0 angekommen ist. \0 ist ja nur dann wenn ich ein String 
abschließen will oder der Datensatz komplett übertragen wurde.

von Eberhard (Gast)


Lesenswert?

!= ... ok passt

von Karl H. (kbuchegg)


Lesenswert?

Eberhard schrieb:
> Erstmal vielen Dank für die Beispiele  Hilfe  Anreize!
>
> Karl Heinz Buchegger schrieb:
>> while (source[index] != '\0' &&
>>          source[index] != 0x16)
>
> Momentan ist es so, dass ich weiß, nach einem 0x16 ist der ersten
> Datensatz fertig und der nächste kommt dran, hier wird geprüft ob ein
> 0x16 und ein \0 angekommen ist.

Nein.
Du hast die ! nicht bedacht.
Die Schleife läuft so lange, so lange das nächste Zeichen weder ein \0 
noch ein 0x16 ist. Mit anderen Worten, solange das alles ganz normale 
Zeichen sind, läuft die Schleife. Erst beim nächsten \0 bzw. 0x16 bricht 
die Schleife ab, je nachdem was dann eben gerade vorliegt.

von Eberhard (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Nein.
> Du hast die ! nicht bedacht.
> Die Schleife läuft so lange, so lange das nächste Zeichen weder ein \0
> noch ein 0x16 ist. Mit anderen Worten, solange das alles ganz normale
> Zeichen sind, läuft die Schleife. Erst beim nächsten \0 bzw. 0x16 bricht
> die Schleife ab, je nachdem was dann eben gerade vorliegt.

Ja habe es selbst gemerkt!
Das ist wirklich genial! Prinzipiell versucht ich immer selbst auf sowas 
zu kommen, aber wenn man C nur mit Probieren und GCC Tutorial lernt, 
stößt man oft an seine Grenzen!

von Karl H. (kbuchegg)


Lesenswert?

Eberhard schrieb:
> Karl Heinz Buchegger schrieb:
>> Nein.
>> Du hast die ! nicht bedacht.
>> Die Schleife läuft so lange, so lange das nächste Zeichen weder ein \0
>> noch ein 0x16 ist. Mit anderen Worten, solange das alles ganz normale
>> Zeichen sind, läuft die Schleife. Erst beim nächsten \0 bzw. 0x16 bricht
>> die Schleife ab, je nachdem was dann eben gerade vorliegt.
>
> Ja habe es selbst gemerkt!
> Das ist wirklich genial! Prinzipiell versucht ich immer selbst auf sowas
> zu kommen, aber wenn man C nur mit Probieren und GCC Tutorial lernt,
> stößt man oft an seine Grenzen!


De Morgan Regel
1
  nicht( A oder B )   <==>   ( nicht A ) und ( nicht B )
1
  A      ist das Zeichen ein \0
2
  B      ist das Zeichen in 0x16
1
   NICHT( ist das Zeichen ein \0  ODER  ist das Zeichen ein 0x16 )
in 'Deutsch' übersetzt: "wenn nicht gilt, dass das Zeichen ein \0 oder 
ein 0x16 ist" ... dann kann es keines von beiden sein.

mit De Morgan wird daraus
1
   NICHT( ist das Zeichen ein \0  ODER ist das Zeichen ein 0x16 )
2
3
      <==>
4
5
   (ist das Zeichen NICHT \0) UND (ist das Zeichen NICHT 0x16)

von Amateur (Gast)


Lesenswert?

Pass' aber auf, wenn "asynchron" der Stecker gezogen wird.
Sonst wartet irgendjemand schon mal auf das Ende des begonnenen 
Datenpaketes.

von Eberhard (Gast)


Lesenswert?

Amateur schrieb:
> Pass' aber auf, wenn "asynchron" der Stecker gezogen wird.
> Sonst wartet irgendjemand schon mal auf das Ende des begonnenen
> Datenpaketes.

Das wäre äußerst ungünstig das stimmt!

von Eberhard (Gast)


Lesenswert?

Guten Abend zusammen,

ich habe in dem Code noch ein paar Sachen angepasst.
Vielen Dank noch mal für die Hilfe!

Hier erstmal der Struct:

typedef struct Data
{
  char ch_data_name_one[12];
  char ch_data_page_one[12];
  char ch_data_name_secound[12];
  char ch_data_page_secound[12];
  char ch_data_name_third[12];
  char ch_data_page_third[12];
}S_Data;
S_Data g_SData;


uint8_t NextString( char *target, char *source, uint8_t index )
{
    while (source[index] != '\0' && source[index] != 0x17)
    {
        *target = source[index];
  target++;
  index++;
    }

    *target = '\0';
    index++;

    return index;
}


void get_data(void)
{
     uint8_t index = 0;

index = NextString(&g_SData.ch_data_name_one, &s_CmdBuffer, index);
index = NextString(&g_SData.ch_data_page_one, &s_CmdBuffer, index);
index = NextString(&g_SData.ch_data_name_secound, &s_CmdBuffer, index);
index = NextString(&g_SData.ch_data_page_secound, &s_CmdBuffer, index);
index = NextString(&g_SData.ch_data_name_third, &s_CmdBuffer, index);
index = NextString(&g_SData.ch_data_page_third, &s_CmdBuffer, index);
}

von Eberhard (Gast)


Lesenswert?

Wenn ich jetzt eine Zeichekette senden möchte, angenommen "bla"
muss ich ja am Ende des Zeichenkette ein 0x17 mit schichen, damit ich 
weiß, dass es hier zu Ende ist.

In C kann ich das ja nicht einfach hinten anhängen zudem ist es ja ein 
Char 0x17 also 8 Bit.

hw_rs232_send_string("bla (\)ETB" );
So habe ich es schon versucht, leider ohne Erfolg.

von Stefan E. (sternst)


Lesenswert?

1
...("bla\x17");
oder
1
#define ETB "\x17"
2
3
...("bla"ETB);

von Eberhard (Gast)


Lesenswert?

Stefan Ernst schrieb:
> ...("bla\x17");oder#define ETB "\x17"
>
> ...("bla"ETB);

Danke für die Antwort, aber genau soweit war ich schon.
Es wird ausgegeben...

---> (4x16 LCD)

bla bla bla bla bla
 bla bla bla bla
bla

usw. also irgendwie stimmt da was noch nicht so ganz.

von Karl H. (kbuchegg)


Lesenswert?

Eberhard schrieb:
> Stefan Ernst schrieb:
>> ...("bla\x17");oder#define ETB "\x17"
>>
>> ...("bla"ETB);
>
> Danke für die Antwort, aber genau soweit war ich schon.
> Es wird ausgegeben...
>
> ---> (4x16 LCD)
>
> bla bla bla bla bla
>  bla bla bla bla
> bla
>
> usw. also irgendwie stimmt da was noch nicht so ganz.

Ja das ist meistens so, dass Programme nicht so ganz auf Anhieb 
funktionieren. Dann betritt man die Phase die man 'Debuggen' nennt.

-> Erst mal feststellen, ob beim Empfänger hbei der Auswertung hier in 
der Funktion der String überhaupt so aussieht, wie er aussehen sollte.


PS: zum Debuggen kannst du ja auch das 0x17 erst mal durch ein anderes 
Zeichen ersetzen, zb ein '*'. Denn im Prinzip ist es ja wurscht, welches 
Zeichen (welchen ASCII Code) du nimmst, solange der in den Nutzdaten 
nicht vorkommt. Und zb ein '*' hat den Vorteil, dass du im Debugger 
keine Probleme mit Strings hast, die irgendwelche nicht darstellbare 
'Sonderzeichen' beinhalten.

Läuft alles, dann kann man den '*' ja wieder durch 0x17 austauschen.

von Karl H. (kbuchegg)


Lesenswert?

Hast du eigentlich hier
1
  ...
2
3
  *target = '\0';
4
  if(source[index] != '\0')                   
5
    index++;
6
7
  return index;
8
}

das if nicht gesehen oder hast du das absichtlich rausgeworfen.
Dieses if hat seinen Grund: Es soll verhindern, dass index hinter den 
Eingangsstring laufen kann, wenn im Eingangsstring irgendwas schief 
läuft und zb gar keine 6 Pakete enthalten sind.

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.