float zu 4x8Bit und zurück

Gast #3342617
Lesenswert?

Hallo,

ich messe mit dem ADC die Spannung eines Stromwandlers und berechne 
daraus einen Messwert. Dieser liegt mir als float Zahl vor.

Die float Zahl (vm) möchte ich via CAN-Nachricht verschicken und beim 
Empfänger wieder in eine float Zahl wandeln.

Das mache ich bisher so:

Senden:
1
uint8_t mm_data[4] = {0};
2
uint8_t *mm_data_ptr;
3
  
4
mm_data_ptr = mm_data;    
5
memcpy((void*)&mm_data, &vm, sizeof(float));
6
    
7
for(uint8_t i=0;i<4;i++)
8
{
9
msg.data[i] = *mm_data_ptr;
10
mm_data_ptr++;
11
}
12
can_send_message(&msg);
Empfangen:
1
float data;
2
memcpy(&data, can_dump_frame->data, sizeof(float));
3
printf("Value: %f A\n",data);
Ist es so richtig?
Oder würdet ihr es anders machen?
Bekomme irgendwie nicht das richtige angezeigt beim printf() ....


Grüße
Persönliche Seite #3342627
Lesenswert?

qwertz schrieb:
> Ist es so richtig?

Nur falls auf beiden Seiten float die gleiche Darstellung hat.

In dem Fall brauchst du auch kein mm_data sondern kannst die Adresse des 
float direkt in die Senderoutine (die wohl const void* nimmt) geben.

Ansonsten ist das Forum voll mit dem Thema, es wird gefühlt ca. 1x pro 
Woche durchgekaut.
#3342699
Lesenswert?

qwertz schrieb:

> uint8_t mm_data[4] = {0};
> uint8_t *mm_data_ptr;
>
> mm_data_ptr = mm_data;
> memcpy((void*)&mm_data, &vm, sizeof(float));

Da kopierst du ja schon die Bytes ins Array

> for(uint8_t i=0;i<4;i++)
> {
> msg.data[i] = *mm_data_ptr;
> mm_data_ptr++;
> }

wozu dann nochmal kopieren?

wozu eigentlich die extra Pointer Variable und das extra Array? Wenn in 
msg sowieso schon ein Byte Array enthalten ist, warum lässt du memcpy 
die Bytes nicht gleich dort hinein kopieren?

> Bekomme irgendwie nicht das richtige angezeigt beim printf() ....

Dann lass dir halt mal die Bytes ausgeben und sieh nach, ob die beim 
Sender und beim Empfänger identisch sind.

Wenn sie es sind, dann verwenden die beiden Parteien wohl 
unterschiedliche Floating Point Darstellungen. Muss nicht sein, kann 
aber sein. Der Bytevergleich macht dich sicher. Denn dann weißt du 
zumindest schon mal, dass auf der CAN Übertragung nichts passiert ist 
und der Empfänger genau das zu sehen kriegt, was der Sender auch 
weggeschickt hat.
Gast #3342865
Lesenswert?

> Mit float hast du nur Ärger am Hals.

Okay, nun verpacke ich eine 32Bit zahl in den CAN_Frame. Das ganze wird 
zunächst in einen Ringpuffer geschrieben und später verschickt:

In Puffer:
1
memcpy((void*)&mm_buf[mm_buf_h], &vm, sizeof(uint32_t)); 
2
...

Senden:
1
for(tt; tt != th; tt = (tt + sizeof(uint32_t)) & (MM_BUFSIZE -1))
2
{
3
  msg.id=ID;    
4
  mm_buff_ptr = mm_buff + tt;
5
    
6
  for(i=0;i<4;i++)
7
  {
8
    msg.data[i] = *mm_buff_ptr;
9
    mm_buff_ptr++;
10
  }
11
  
12
  can_send_message(&msg);
Empfangen:
1
memcpy(&dat, can_dump_frame->data, sizeof(long));
2

3
printf("Value: %i A\n",dat);

Es erscheint der richtige Wert im Terminal.
Allerdings nur eine 4-Stellige Zahl.
Wo ist der Rest meiner 32 Bit geblieben?
Gast #3342922
Lesenswert?

> %i und long passen nicht zueinander.
Was nutze ich dann für long?
Durch %li ändert sich nichts.


Ich würde es ja eigentlich gern als float Zahl auf dem Terminal 
ausgeben:

long dat;

memcpy(&dat, can_dump_frame->data, sizeof(long));
float data = dat / 1000;
printf("Value: %f A\n",data);


Natürlich funktioniert es so nicht :(
Was mache ich falsch?

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