Forum: Mikrocontroller und Digitale Elektronik Größere Datenmenge über UART


von Jack (Gast)


Lesenswert?

Hi

ich möchte 4 integer Variablen übertragen. Dazu wollte ich sie 
aneinanderreihen und als einen langen String schicken.

Sender:
1
char send[80] = "";
2
uint32_t senden= 0;
3
4
//bx hat 3 Stellen, der Rest 2 Stellen
5
senden= P_Ry1*1000*100*100+P_Ly1*1000*100+1000*by+bx; 
6
7
itoa(senden,(char *)send, 10);
8
9
uart_puts((char *)send); 
10
uart_puts("\n");


Empfänger:
1
  char uart_string[80] = "";
2
  uint32_t buffer=0;
3
  char result[10];
4
5
  buffer=atoi((const char *)uart_string);
6
      
7
8
  bx= buffer%1000;
9
  itoa(bx, result1,10);
10
      
11
  by= (buffer/1000)%100;
12
  itoa(by, result2,10);
13
14
  P_Ly1=(buffer/100000)%100;
15
  itoa(P_Ly1, result3,10);
16
17
  P_Ry1=(buffer/10000000)%100;
18
  itoa(P_Ry1, result4,10);

allerdings bekomme ich immer nur Stücke von 5 Zeichen und nicht mehr

Danke

von Dario B. (abcd)


Lesenswert?

> ich möchte 4 integer Variablen übertragen. Dazu wollte ich sie
> aneinanderreihen und als einen langen String schicken.

Waum denn? Was spricht dagegen, die Ints als asci, und zwischen den 
werten ein "\n" zu senden? Dann brauchst du sie beim Empfänger nicht 
wieder auseinander zu pflücken.

Hast du den die ÜPbertragung mal sonnstwie durchgetestet?

von Andreas (Gast)


Lesenswert?

Jack schrieb:
> itoa(senden,(char *)send, 10);

itoa ist, wie der Name schon sagt, für Integer-Variablen gedacht. In 
Deinem Fall sind die 16 Bit breit. Für 32 Bit breite Variablen gibt es 
ltoa. Vermutlich wirst Du damit bessere Ergebnisse erziehlen.

von Jack (Gast)


Lesenswert?

Dario B. schrieb:
> Hast du den die ÜPbertragung mal sonnstwie durchgetestet?

Ich habe die Übertragung egbenfalls an den Terminal geschickt und sie so 
getestet

Dario B. schrieb:
> Waum denn? Was spricht dagegen, die Ints als asci, und zwischen den
> werten ein "\n" zu senden?

Ich wollte nicht das Risiko eingehen, dass ich mit den empfangenen Werte 
vielleicht durcheinander komme und mir so den Programmablauf zerstörre.
Allerdings wäre das meine 2te Lösung gewesen, wollte erstmal das andere 
testen.

Andreas schrieb:
> itoa ist, wie der Name schon sagt, für Integer-Variablen gedacht. In
> Deinem Fall sind die 16 Bit breit. Für 32 Bit breite Variablen gibt es
> ltoa. Vermutlich wirst Du damit bessere Ergebnisse erziehlen.

guter Tipp, allerdings kann ich den Befehl Itoa nicht verwenden, er 
findet ihn trotz einbinden von #include <stdlib.h> nicht.
Was fehlt noch?

von jonas biensack (Gast)


Lesenswert?

Itoa != itoa...

von Dieter K. (Gast)


Lesenswert?

jonas biensack schrieb:
> Itoa != itoa...

das auch, ist ja einmal ein Großbuchstabe "i" und ein Kleinbuchstabe "i"

Abgesehen davon heißt das

ltoa vs. itoa
^
L

von Jack (Gast)


Lesenswert?

Dieter K. schrieb:
> ltoa vs. itoa
> ^
> L

Danke, das war das Problem

allerdings bringt es keine Besserung, es fehlen immernoch Daten bzw er 
schickt nur 4 Zahlen

nochmal die uart funktionen
1
void uart_init(void)
2
{
3
  UBRR1 = 103;
4
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1); 
5
  UCSR1C = (1<<USBS1)|(3<<UCSZ10);        
6
7
}
8
9
int uart_putc(unsigned char c) 
10
{
11
    while (!(UCSR1A & (1<<UDRE1)))  
12
    {
13
    }                             
14
 
15
    UDR1 = c;                      
16
    return 0;
17
}
18
 
19
 
20
21
void uart_puts (char *s)
22
{
23
    while (*s)
24
    {   
25
        uart_putc(*s);
26
        s++;
27
    }
28
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jack schrieb:

> ich möchte 4 integer Variablen übertragen. Dazu wollte ich sie
> aneinanderreihen und als einen langen String schicken.

Was sind bei Dir die 4 Integer-Variablen? Welchen Wertebereich haben 
sie? Unter Umständen kannst Du auch gar nicht 4 Werte in einen 
32-Bit-Integer packen, weil sie z.B. negativ sind oder größer als 100 
sind.

Ich würde alle 4 Werte in den String "send" packen - durch Leerzeichen 
getrennt:

Beim Sender:

Elegant, aber speicherplatz-aufwendig:
1
    sprintf (send, "%d %d %d %d\n", P_Ry1, P_Ly1, by, bx);
2
    uart_puts(send);

Weniger elegant, aber vom Speicherplatz sparsamer:
1
    itoa (P_Ry1, send, 10);
2
    strcat (send, " ");
3
    itoa (P_Ly1, send + strlen (send), 10);
4
    strcat (send, " ");
5
    itoa (by, send + strlen (send), 10);
6
    strcat (send, " ");
7
    itoa (bx, send + strlen (send), 10);
8
    strcat (send, "\n");
9
    uart_puts(send);

Beim Empfänger:

Elegant, aber speicherplatz-aufwendig:
1
  if (sscanf (uart_string, "%d %d %d %d", &P_Ry1, &P_Ly1, &by, &bx) != 4)
2
  {
3
      ... // Fehler beim einlesen
4
  }
5
  else
6
  {
7
      ... // tue was
8
  }

Weniger elegant, aber vom Speicherplatz sparsamer:
1
    char * p;
2
3
    P_Ry1 = atoi(uart_string);
4
    p = strchr (uart_string, ' ');
5
6
    if (p)
7
    {
8
       p++;
9
       P_Ly1 = atoi(p);
10
11
       p = strchr (p, ' ');
12
13
       if (p)
14
       {
15
         p++;
16
         by = atoi(p);
17
18
         p = strchr (p, ' ');
19
20
         if (p)
21
         {
22
           p++;
23
           bx = atoi(p);
24
         }
25
       }
26
    }
27
28
   if (p)
29
   {
30
       ... // tue was
31
   }
32
   else
33
   {
34
       ... // Fehler
35
   }

Letzteres könnte man schöner machen, indem man sich eine eigene 
Scan-Funktion schreibt.
1
uint8_t
2
myscan (char * p, uint8_t pos, uint8_t * valuep)
3
{
4
    while (pos)
5
    {
6
        p = strchr (p, ' ');
7
8
        if (!p)
9
        {
10
            return 0;  // FEHLER!
11
        }
12
        p++;
13
        pos--;
14
    }
15
16
    *valuep = atoi (p);
17
    return 1;     // OK!
18
}

Aufruf dann:
1
   if (myscan (uart_string, 0, &P_Ry1) &&
2
       myscan (uart_string, 1, &P_Ly1) &&
3
       myscan (uart_string, 2, &by) &&
4
       myscan (uart_string, 3, &bx))
5
   {
6
       ... // tue was
7
   }
8
   else
9
   {
10
       ... // Fehler
11
   }

Ist nicht getestet, sollte aber so laufen.

von Jack (Gast)


Lesenswert?

dickes danke für deine mühe, ich werde es nachher mal einbauen und 
testen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jack schrieb:
> dickes danke für deine mühe, ich werde es nachher mal einbauen und
> testen

Du hattest leider nicht meine Fragen beantwortet:

Was sind bei Dir die 4 Integer-Variablen? Welchen Wertebereich haben
sie?

Wäre nett, wenn Du dazu noch eine Aussage treffen würdest. Das wäre 
schon wichtig für den Code, den ich da oben hinschrieb. Dieser ist 
momentan darauf ausgerichtet, dass Deine 4 Variablen tatsächlich 
Integer-Variablen (also 16 Bit breit) sind, d.h. bei Dir steht irgendwo:

int P_Ry1;
int P_Ly1;
int by;
int bx;

Zeige bitte die Definition Deiner Variablen. Die hast Du in Deinen 
Code-Listings leider immer weggelassen.

Wenn sie vom Typ int sind, muss die Zeile

  myscan (char * p, uint8_t pos, uint8_t * valuep)

in

  myscan (char * p, uint8_t pos, int * valuep)

geändert werden, sonst kracht es.

von Karl H. (kbuchegg)


Lesenswert?

Jack schrieb:

> Ich wollte nicht das Risiko eingehen, dass ich mit den empfangenen Werte
> vielleicht durcheinander komme und mir so den Programmablauf zerstörre.

Dann stell jeder Zahl einen Buchstaben vorran, der eindeutig 
kennzeichnet, worum es sich bei dieser Zahl handelt.

Dann sieht deine 'Auswertung' so aus
1
  ...
2
  ... irgendwo ist eine neue Zeile hergekommen. Sie steht in uart_string
3
4
  if( uart_string[0] == 'X' )
5
      bx = atoi( &uart_string[1] );
6
7
  else if( uart_string[0] == 'Y' )
8
      by = atoi( &uart_string[1] );
9
10
  else if( uart_string[0] == 'L' )
11
      P_Ly1 = atoi( &uart_string[1] );
12
13
  else if( uart_string[0] == 'R' )
14
      P_Ry1 = atoi( &uart_string[1] );

und das Versenden so:
1
void send_value( char label, int value )
2
{
3
  char buffer[10] = "";
4
5
  itoa( value, buffer, 10 );
6
7
  uart_putc( label );
8
  uart_puts( buffer ); 
9
  uart_putc( '\n' );
10
{
11
12
int main()
13
{
14
15
  ......
16
17
  send_value( 'X', bx );
18
  send_value( 'Y', by );
19
  send_value( 'L', P_Ly1 );
20
  send_value( 'R', P_Ry1 );

Simpel, einfach, durchschaubar und nicht besonders fehleranfällig.
Und das schönste am Ganzen: wenn sich dann tatsächlich irgendwann nur 1 
einziger Wert ändert, dann brauchst du auch nur diesen einen Wert der 
Gegenstelle übermitteln.

von Jack (Gast)


Lesenswert?

klar, es sind momentan normale integer Variablen, also 16 bit
aber im Prinzip würden 8 bit auch reichen, daher wollte ich sie noch 
ändern

danke

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.