Größere Datenmenge über UART

Gast #2253690
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
#2253710
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?
Gast #2253901
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?
Gast #2254090
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
}
Moderator Persönliche Seite #2254180
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.
Moderator Persönliche Seite #2254264
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.
#2254635
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren