Forum: Mikrocontroller und Digitale Elektronik canbus / SN65HVD230 / lib?


von Ray M. (ray_m)


Lesenswert?

hi @all,

ich würde gern 2 arm cortex via can minenander reden lassen,
dazu verwende ich zwei SN65HVD230, das funktioniert
alles mit der flexcan-lib schon ganz gut

mit flexcan kann man aber keine beliebigen messages verschicken
da die lib eine can-message so definiert

typedef struct CAN_message_t {
  uint32_t id;      // can identifier
  uint8_t ext;      // identifier is extended
  uint8_t len;      // length of data
  uint16_t timeout; // milliseconds, zero will disable waiting
  uint8_t buf[8];   // data
} CAN_message_t;

was dann zu folgendem führt:
  int a = 1234;
  msg.id = 0x100;
  msg.len = sizeof(a);
  memcpy(msg.buf, &a, sizeof(a));
  CANbus.write(msg);

nun will ich aber beliebige messages verschicken und frage mich ob
nicht jemand hier im forum eine tip, eine lib oder link für mich hat ...

ich würde gern sowas machen:

struct trData {
  unsigned int a = 18;
  signed int   b = -23;
  float        c = 14.3;
  int16_t      d = 21653;
  byte         e = 1;
} myData;

was dann zu folgendem führen soll:
  CANbus.write(0x100, myData.a);
  CANbus.write(0x101, myData.b);
  CANbus.write(0x102, myData.c);
  ...

von hp-freund (Gast)


Lesenswert?

Bin kein can Experte, aber wie es aussieht möchtest Du eine feste 
Zuordnung msg.id <> Datentyp.
Das sollte sich doch mit einer festen Sendeseitigen Formatierung z.B.:
a -> len(a) -> msg.id
lösen lassen.

Der Empfänger wertet in einer case Anweisung die msg.id aus und gibt den 
entsprechenden Wert/Typ passend zur id wieder aus.

von Ray M. (ray_m)


Lesenswert?

und wie soll ich meine verschiedenen datentypen
hier "uint8_t buf[8];" rienpacken ?

von STK500-Besitzer (Gast)


Lesenswert?

Ray M. schrieb:
> und wie soll ich meine verschiedenen datentypen
> hier "uint8_t buf[8];" rienpacken ?

als Union...
Oder du baust dir passend für jeden Datentyp eine Funktion, die aus dem 
Datentyp ein Byte-Array macht.
Datentypen sind i.d.R. Vielfache eines Bytes.

von Ray M. (ray_m)


Lesenswert?

gibt es bei union nicht wieder das padding problem ?
das mit dem c ist schon eine echte bit-friemelei ;(

hast du ein example für mich ?

von hp-freund (Gast)


Lesenswert?

Ray M. schrieb:
> und wie soll ich meine verschiedenen datentypen
> hier "uint8_t buf[8];" rienpacken ?


Genau wie im Beispiel oben. Ich sehe 2 Möglichkeiten je nach 
Anforderung:

1. Es sollen immer nur einzelne Werte übertragen werden, dann würde ich 
eine Funktion schreiben wie:
1
CANbus.writeFloat(float f)
2
{
3
  msg.id = 0x102;
4
  msg.len = sizeof(f);
5
  memcpy(msg.buf, &f, msg.len);
6
  CANbus.write(msg);
7
}
und antsprechend für die anderen Typen.

2. Es soll das gesamte struct auf einmal übertragen werden, dann kannst 
Du es in Teile von 8 byte "zerhacken" und auf der Empfängerseite wieder 
in das gleiche struct schreiben. Dann brauchst Du dir über die 
Datentypen die unterwegs sind keine Gedanken zu machen.

von Ray M. (ray_m)


Lesenswert?

wo ist dann der unterschied zwischen CANbus.writeFloat und 
CANbus.writeSigInt ?

dann kann ich ja auch einfach folgendes schreiben

  unsigned int a = 1234;
  msg.id = 0x100;
  msg.len = sizeof(a);
  memcpy(msg.buf, &a, sizeof(a));
  CANbus.write(msg);

  signed int b = -62662;
  msg.id = 0x101;
  msg.len = sizeof(b);
  memcpy(msg.buf, &b, sizeof(b));
  CANbus.write(msg);

  usw...

nur dann packe ich ein "signed int" in ein "uint8_t buf[8];"
und da kommt auf der anderen seite unfug raus ...

irgendwas versteh ich hier nicht ...

: Bearbeitet durch User
von hp-freund (Gast)


Lesenswert?

Ray M. schrieb:
> dann kann ich ja auch einfach folgendes schreiben

Richtig. Darum meinte ich ob Du die Werte einzeln oder am Stück 
übertragen möchtest. Mit der Funktion ist es einzeln sehr einfach.

Ray M. schrieb:
> nur dann packe ich ein "signed int" in ein "uint8_t buf[8];"
> und da kommt auf der anderen seite unfug raus ...

Das Problem liegt also in der Rückwandlung der 8 byte in den richtigen 
Datentyp.
Das meinte ich mit case:
1
switch(msg.id) {
2
  case 0x102: memcpy(&f, msg.buf, msg.len); break;
3
        .
4
  .
5
}

von hp-freund (Gast)


Lesenswert?

Wobei ich mir mit dem memcpy und den & jetzt nicht sicher bin.
Müsste man testen.

von Ray M. (ray_m)


Lesenswert?

ich mach mir einen kaffee und teste das gleich ...

danke für deine hilfe ;)

von Ray M. (ray_m)


Lesenswert?

ok

auf der sender-seite hab ich jetzt

struct DataSet {
    unsigned int a = 3526;
    signed int b   = -12;
    float c        = 14.2;
    byte d         = 1;
} sysData;

und dann

  msg.id = 0x100;
  msg.len = sizeof(sysData.a);
  memcpy(msg.buf, &sysData.a, sizeof(sysData.a));
  CANbus.write(msg);

  msg.id = 0x101;
  msg.len = sizeof(sysData.b);
  memcpy(msg.buf, &sysData.b, sizeof(sysData.b));
  CANbus.write(msg);

  msg.id = 0x102;
  msg.len = sizeof(sysData.c);
  memcpy(msg.buf, &sysData.c, sizeof(sysData.c));
  CANbus.write(msg);

  msg.id = 0x103;
  msg.len = sizeof(sysData.d);
  memcpy(msg.buf, &sysData.d, sizeof(sysData.d));
  CANbus.write(msg);

der empfänger ist

struct DataSet {
    unsigned int a;
    signed int b;
    float c;
    byte d;
} sysData;

  while ( CANbus.read(rxmsg) ) {
    switch(rxmsg.id) {
      case 0x100: memcpy(&sysData.a, rxmsg.buf, sizeof(rxmsg.buf) );; 
break;
      case 0x101: memcpy(&sysData.b, rxmsg.buf, sizeof(rxmsg.buf) );; 
break;
      case 0x102: memcpy(&sysData.c, rxmsg.buf, sizeof(rxmsg.buf) );; 
break;
      case 0x103: memcpy(&sysData.d, rxmsg.buf, sizeof(rxmsg.buf) );; 
break;
    }
  }

das scheint zu funktionieren, nur nicht für "byte d", da kommt
immer 0 beim empfänger an ???

von Ray M. (ray_m)


Lesenswert?

wenn man jetzt in c auch noch folgendes schreiben könnte

my $c = 0;
foreach my $i (keys sysData) {
  msg.id = 0x10$c;
  msg.len = sizeof($sysData->{$i});
  memcpy(msg.buf, $sysData->{$i}, sizeof($sysData->{$i}));
  CANbus.write(msg);
}

müsste man nicht alles zu fuß machen, aber das ist
ja ein feuchter traum ;(

von hp-freund (Gast)


Lesenswert?

Auch kein Problem.
Leg ein Array mit den Längen der Variablen an und sende in einer 
Schleife mit Index-Werten.

von Ray M. (ray_m)


Lesenswert?

grrr ...

machst du mir ein bsp ;)

von hp-freund (Gast)


Lesenswert?

Wo bleibt denn dann dein Spass?

Du bist übrigens kurz vor meinem Vorschlag 2 von 12:17.
Ich wette das die flexcan Ersteller sich auch schon Gedanken gemacht 
haben wie man mehr als 8 byte sendet...

von Ray M. (ray_m)


Lesenswert?

hp-freund schrieb:
> Wo bleibt denn dann dein Spass?

ein link ? ;)

> Du bist übrigens kurz vor meinem Vorschlag 2 von 12:17.
> Ich wette das die flexcan Ersteller sich auch schon Gedanken gemacht
> haben wie man mehr als 8 byte sendet...

das kann gut sein, aber mangels docu und/oder eines bsp.
hänge ich da in der luft rum und wir unterhalten uns ;)

siehe
  https://github.com/teachop/FlexCAN_Library

von hp-freund (Gast)


Lesenswert?

Was mir mehr Sorgen gemacht hat ist das byte d.
Versuch mal uint8_t an Stelle von byte.

***************

Noch ein letzter Tip zu der Variante 2.

Frage die Grösse des struct ab:
1
sizeDataSet=sizeof(struct DataSet);

Pack das struct in einen Puffer mit dieser Grösse und sende:
puffer[0],Länge=8 bis
puffer[8],RestLänge

Viel Spaß ;-)

von hp-freund (Gast)


Lesenswert?

Ach, Du wolltest ja noch einen link.
Bitte sehr:

http://www.wachtler.de/ck/8_7_struct_union.html

von Ray M. (ray_m)


Lesenswert?

danke ...
damit sollte ich durchkommen ... ;)

von Ray M. (ray_m)


Lesenswert?

hp-freund schrieb:
> Was mir mehr Sorgen gemacht hat ist das byte d.
> Versuch mal uint8_t an Stelle von byte.

wer mist hinschreibt bekommt mist raus

das ist von mir unsinn
  memcpy(&sysData.a, rxmsg.buf, sizeof(rxmsg.buf) )

so tut es ...
  memcpy(&sysData.a, rxmsg.buf, rxmsg.len )

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.