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); ...
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.
und wie soll ich meine verschiedenen datentypen hier "uint8_t buf[8];" rienpacken ?
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.
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 ?
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.
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
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 | }
|
Wobei ich mir mit dem memcpy und den & jetzt nicht sicher bin. Müsste man testen.
ich mach mir einen kaffee und teste das gleich ... danke für deine hilfe ;)
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 ???
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 ;(
Auch kein Problem. Leg ein Array mit den Längen der Variablen an und sende in einer Schleife mit Index-Werten.
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...
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
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ß ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.