Forum: Compiler & IDEs Struct per Uart Senden


von fridrich (Gast)


Lesenswert?

Hallo Freunde,
ich sitze vor einem Problem, ich möchte eine Structur per Uart Versenden 
aber es klappt nicht.
1
volatile struct
2
{
3
  char start;
4
  uint8_t len;
5
  double Temp_array[3] ;
6
  char end;
7
}proto, Proto;
8
9
Proto.start=0x02;
10
Proto.end=0x03;
11
Proto.len= sizeof(Proto.Temp_array);
12
13
void Transmit(void *cData,uint8_t len)
14
{
15
  while(len-- > 0)
16
  {
17
    uart_putc( *(char *)cData);  // shift out data
18
    cData++;
19
  }
20
21
}
22
void main(int)
23
{
24
     while(1)
25
    {
26
    _delay_ms(500);
27
    Transmit(Proto.start,sizeof(Proto));
28
    }
29
}
Leider kommt nur Müll aus der Uart raus .
Die Uart Fuktion von Peter Fleury fuktioniert sonst bestens es liegt 
also an meiner  Trasmit Funktion.
Ich komme aber nicht auf den Fehler Bitte helft mir !

Danke gruß
Fridrich

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Der UART versendet einzelne Bytes.

also die struct in Bytes zerlegen, die einzeln übertragen und
dann beim Empfänger wieder passend zusammenbauen.

Senden in etwa so:
1
unsigned char *p;
2
3
for ( p=(unsigned char *) &Proto; (p - (unsigned char *) &Proto) < sizeof(Proto); p++)
4
  uart_putchar( *p);

von holger (Gast)


Lesenswert?

void Transmit(uint8_t *cData,uint8_t len)
{
  while(len-- > 0)
  {
    uart_putc(cData);  // shift out data
    cData++;
  }

}


Transmit(Proto,sizeof(Proto));

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

> uart_putc(cData);

;-)

> uart_putc(*cData);

von holger (Gast)


Lesenswert?

>;-)
>
>> uart_putc(*cData);

Ok!

von Konrad S. (maybee)


Lesenswert?

fridrich schrieb:
> cData++;
Besser:
1
 ((char *)cData)++;
damit klar ist, dass der Pointer um ein Byte erhöht werden soll.

fridrich schrieb:
> Transmit(Proto.start,sizeof(Proto));
So:
1
 Transmit(&Proto.start,sizeof(Proto));
oder besser:
1
 Transmit(&Proto,sizeof(Proto));
weil die Adresse der Struktur gemeint ist.

Bedenklich ist:
fridrich schrieb:
> volatile struct
was darauf hindeutet, dass die Inhalte der Struktur aus einer ISR heraus 
modifiziert werden. Wenn das mitten in der Übertragung passiert, dann 
empfängst du evtl. inkonsistente Daten.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

fridrich schrieb:
> Hallo Freunde,
> ich sitze vor einem Problem, ich möchte eine Structur per Uart Versenden
> aber es klappt nicht.

Bedenke, dass die Datenstruktur auf Quell- und Zielsystem verschieden 
aufgebaut sein kann. Das fängt mit dem Alignment an und geht dann über 
den CPU-Endian bis hin zum (möglich verschiedenen) Format eines 
double-Wertes.

Eine portable Übertragung geht nur über eine ASCII-Präsentation der 
einzelnen Struct-Member.

von Rolf Magnus (Gast)


Lesenswert?

Konrad S. schrieb:
> fridrich schrieb:
>> cData++;
> Besser: ((char *)cData)++;
> damit klar ist, dass der Pointer um ein Byte erhöht werden soll.

Nein. Das ergibt einen Fehler, da man das Ergebnis eines Casts nicht 
inkrementieren kann. Wäre auch irgendwie sinnlos.

Noch so am Rande:

fridrich schrieb:
> void main(int)

Das gehört umgedreht:
1
int main(void)

von Konrad S. (maybee)


Lesenswert?

Rolf Magnus schrieb:
> Nein. Das ergibt einen Fehler, da man das Ergebnis eines Casts nicht
> inkrementieren kann. Wäre auch irgendwie sinnlos.

Ok, das sehe ich ein. Scheint so, als hätte ich so eine Konstruktion 
noch nie eingesetzt seit der gcc das überprüft. Erstaunlich.

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Konrad S. schrieb:
> Ok, das sehe ich ein. Scheint so, als hätte ich so eine Konstruktion
> noch nie eingesetzt seit der gcc das überprüft. Erstaunlich.

Das ist bestimmt der Optimierung zum Opfer gefallen ;)

von fridrich (Gast)


Lesenswert?

Vielen Dank für Eure Hilfe  jetzt klappt es!

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ich muss das nochmal aufwärmen. Ich hänge am gleichen Problem, kann 
lesen wie ich möchte, ich weiß nicht wo der Fehler liegt. Der Datentyp 
passt nicht. So verstehe ich das jedenfalls. Nur was muss ich anders 
machen? Kann mir bitte jemand helfen? Ich nutze ebenfalls die uart Lib 
vom Peter Fleury.
1
struct Nachricht {
2
  uint8_t adress = 0;
3
  uint8_t function = 0;
4
  uint8_t wert = 0;
5
} message;


Deklaration:
1
void sendStruct(uint8_t *structPtr, uint8_t length);


Aufruf:
1
message.adress = 78;
2
message.function = 135;
3
message.wert = 207;
4
sendStruct(&message, sizeof(message));


Funktion:
1
void sendStruct(uint8_t *structPtr, uint8_t length)
2
{   
3
  while(length-- > 0)
4
  {
5
    uart_putc(*structPtr);  // Bytes rausschieben
6
    structPtr++;
7
  }
8
}


Fehlermeldungen:  die Zeile 534 bezieht sich auf den Aufruf
1
Fehler
2
cannot convert 'Nachricht*' to 'uint8_t* {aka unsigned char*}' for argument '1' to 'void sendStruct(uint8_t*, uint8_t)'  
3
C:main.cpp  534
4
Fehler
5
recipe for target 'main.o' failed
6
Makefile  86
7
8
Warnung
9
non-static data member initializers only available with -std=c++11 or -std=gnu++11  
10
main.cpp  130
11
Warnung
12
non-static data member initializers only available with -std=c++11 or -std=gnu++11  
13
main.cpp  131
14
Warnung
15
non-static data member initializers only available with -std=c++11 or -std=gnu++11  
16
main.cpp  132

von Franz (Gast)


Lesenswert?

sendStruct erwartet einen Zeiger auf uint8_t, Du übergibst aber einen 
Zeiger auf struct Nachricht. Du musst also irgendwo den Zeiger auf 
struct Nachricht in einen Zeiger auf uint8_t konvertieren aka "casten".

Du hast zwei Möglichkeiten:
1. Du konvertierst den Zeiger vor dem Aufruf von sendStruct.
2. Du änderst die Funktion sendStruct, so dass sie einen Zeiger auf 
struct Nachricht nimmt statt auf uint8_t. Dann musst Du den Zeiger 
innerhalb von sendStruct konvertieren. Aber Vorsicht: Sowohl der Zeiger, 
den Du an uart_putc übergibst, als auch der Zeiger, der in der Schleife 
inkrementiert wird, muss von Typ uint8_t sein.

Die Warnungen gehen weg, wenn Du das "= 0" in der Deklaration von struct 
Nachricht weglässt.

PS: Der Mischmasch aus Deutsch und Englisch im Code liest sich 
grauenvoll.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

wegen den Warnungen. Seit wann darf man die Structur Variablen nicht 
initialisieren?

deutsch englisch, ich weiß immer nicht wie ich die sinnvoll benennen 
soll.

Typcast habe ich jetzt im Funktionsaufruf gemacht. Danke.
1
struct Nachricht {
2
  uint8_t adresse;
3
  uint8_t funktion;
4
  uint8_t wert;
5
} daten;


Deklaration:
1
void sendStruct(uint8_t *structPtr, uint8_t length);


Aufruf:
1
daten.adresse = 78;
2
daten.funktion = 135;
3
daten.wert = 207;
4
sendStruct((uint8_t*)&daten, sizeof(daten));


Funktion:
1
void sendStruct(uint8_t *structPtr, uint8_t length)
2
{   
3
  while(length-- > 0)
4
  {
5
    uart_putc(*structPtr);  // Bytes rausschieben
6
    structPtr++;
7
  }
8
}

es wird alles fehlerfrei kompiliert.
Leider aber!
Statt der ersten 78 wird ein N übertragen. Übertragen wird
N  '135'  '207'
Ändere ich die Daten, ist immer wieder der erste Wert falsch.
Was ist da los?

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ähm Moment, dass ist ja der ascii Code ...
Nur dann ergeben sich doch Probleme die Daten überhaupt richtig zu 
übertragen?

: Bearbeitet durch User
von Franz (Gast)


Lesenswert?

Veit D. schrieb:
> Hallo,
>
> wegen den Warnungen. Seit wann darf man die Structur Variablen nicht
> initialisieren?

Das darf und durfte man in C in der Form, wie Du es hingeschrieben hast, 
noch nie. In C++ darf man es seit C++11.

Es geht aber folgendermaßen:
1
struct Nachricht {
2
  uint8_t adresse;
3
  uint8_t funktion;
4
  uint8_t wert;
5
} daten = {0, 0, 0};

Oder wenn man Deklaration und Definition trennt:
1
struct Nachricht {
2
  uint8_t adresse;
3
  uint8_t funktion;
4
  uint8_t wert;
5
};
6
7
struct Nachricht daten = {0, 0, 0};

Oder kürzer, aber gleichbedeutend:
1
struct Nachricht daten = {0};

> Leider aber!
> Statt der ersten 78 wird ein N übertragen. Übertragen wird
> N  '135'  '207'
> Ändere ich die Daten, ist immer wieder der erste Wert falsch.
> Was ist da los?

Na dann passt es doch. 'N' ist gleichbedeutend mit 78, siehe 
ASCII-Tabelle. Wenn Du den Zahlenwert sehen willst, musst Du die 
Formatierung der Ausgabe auf Empfängerseite umstellen.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

okay, vielen Dank.

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.