32 Bit lang in 4 Bytes konvertieren und wieder zurück – CAN-Bus

Nach 2 Tagen kann ich es also nicht mehr verstehen.

Ich verwende also den CAN-Bus, um Beschleunigungsmesserdaten und Zeitdaten zu übertragen (die Funktion micros (), wenn weniger als 71 Minuten Daten ausgeben, die lange ohne Vorzeichen sein können), muss die Daten jedoch als Bytes senden Es ist mir gelungen, ein 16-Bit-Int in 2 Bytes zu verschieben, aber ich habe Probleme, diese Methode zu extrapolieren (wird später hinzugefügt), um Longs zu verwenden. Ich habe Probleme, die Vereinigungsmethode zu verstehen, da ich neu in der Erstellung meiner eigenen Funktionen bin, also wie Würden Sie dies erreichen? Bitte so einfach wie möglich 🙂

Kommentare

  • Sie subtrahieren das maximale Byte 3, das von der Summe und von sein kann Das Subtrahieren des maximalen Bytes 2 kann sein, um Byte 3 zu erhalten. Byte 4 ist nur maximales Byte 4 minus Zahl minus maximales Byte 3 +1.

Antwort

Mit Bitshifting und bitweise und Operatoren.

Hier ist ein Beispiel, mit dem Sie extrahieren können die einzelnen Bytes Ihrer Variablen long. Ich denke, es sollte einfach sein, es auf Variablen unterschiedlicher Länge zu erweitern:

void loop() { long a=0x12345678, c=0; byte b[4]; Serial.println("Original:"); Serial.println(a,HEX); delay(1000); Serial.println("Individual bytes:"); for (int i=0; i<4; i++) { b[i]=((a>>(i*8)) & 0xff); //extract the right-most byte of the shifted variable Serial.println(b[i],HEX); delay(1000); } for (int i=0; i<4; i++) { c+=b[i]<<(i*8); } Serial.println("Reconstructed:"); Serial.println(c,HEX); delay(1000); } 

Abhängig davon, welche Bytereihenfolge (Big oder Little Endian) erwartet wird, können Sie dies tun Die Bytes müssen vor dem Senden oder nach dem Empfang neu angeordnet werden.

Kommentare

  • Sehr einfach und leicht verständlich, also danke, jedoch unter “ rekonstruiert “ druckt nur 5678?
  • Haben Sie das Code-Snippet aus meiner Antwort kopiert? Denn wenn ich den Code auf meinem nodemcu ausführe, erhalte ich die richtige Antwort.
  • Ja, ich habe den Code kopiert und eingefügt und void setup () hinzugefügt. und Serial.begin (9600); Damit der Code standardmäßig auf meinem Arduino Nano
  • auf einem 8-Bit-AVR ausgeführt wird, wird auf der rechten Seite der Gleichheit standardmäßig die Int-Arithmetik verwendet, die mit 16 Bit signiert ist. Also habe ich das Array in ein uint32_t in der Schleife umgewandelt. Unsicher, ob das der effizienteste Weg ist, aber es funktioniert! Vielen Dank für Ihre Hilfe
  • ja richtig. Ich habe ‚ nicht an den Arduino-Controller gedacht, als ich das nodemcu anprobierte.

Antwort

Der Typ union ähnelt einem struct, außer dass jedes der Elemente des Elements das belegt gleiche Erinnerung. Wenn Sie ein struct so definieren, dass es zwei Elemente hat – einen 4-Byte-Typ und ein 4-Element-Array eines einzelnen Byte-Typs, können Sie problemlos auf dieselben Daten verweisen als ganzes 4-Byte-Element oder byteweise, wie Sie möchten.

union packed_long { long l; byte b[4]; }; 

Dies ist der Typ, daher müssen Sie die Variable deklarieren, von der sie sein soll dieser Typ:

packed_long mydata; 

Jetzt haben Sie zwei Unterelemente von mydata: l und b[].

Um Ihren long -Wert zu speichern, schreiben Sie in die l Teil:

mydata.l = myaccel.getY(); 

So greifen Sie auf jedes der 4 Bytes zu:

byte1 = mydata.b[0]; byte2 = mydata.b[1]; byte3 = mydata.b[2]; byte4 = mydata.b[3]; 

Auf der Empfangsseite nehmen Sie jedes der 4 Bytes:

mydata.b[0] = canbus.read(); mydata.b[1] = canbus.read(); mydata.b[2] = canbus.read(); mydata.b[4] = canbus.read(); 

Solange Sie die Bytes in derselben Reihenfolge empfangen In dem Sie sie gesendet haben, können Sie jetzt auf Ihren long -Wert in mydata.l zugreifen.

Die tatsächliche Größe von different Typen ist Abhängig vom Compiler und der Architektur möchten Sie Ihren Wert möglicherweise auch als Variable mit bestimmter Größe definieren, um sicherzustellen, dass Sie immer mit 32 Bit arbeiten: int32_t (vorzeichenbehaftete 32-Bit-Ganzzahl) ) oder uint32_t (vorzeichenlose 32-Bit-Ganzzahl).

Antwort

Eine Möglichkeit zum Senden eines Longs besteht darin, das LSB-Byte (CAN-Standard) zu maskieren und zu senden und dann das zu verschieben Der nächste in die LSB-Position für 4 Bytes:

uint32_t data; // Send to CAN bus LSB-first // This method is destructive; data should be a temp if the // Arduino is to retain the data after sending it. for( uint8_t b = 4; b > 0; --b ){ sendByte(data & 0xFF); // send curr byte data >>= 8; // shift that byte away } // Read from CAN bus for( uint8_t b = 4; b > 0; --b ){ data >>= 8; // make room for byte data |= (readByte() << 8); // read next higher byte } // 

Kommentare

  • OK, also CAN-Standard ist zuerst LSB. Wie Sie wissen, senden CAN nach dem, was ich finden kann, ein 8-Byte-Paket. Sind nur ein oder zwei dieser Daten? Würden also für insgesamt 16 Informationsbytes 8 Pakete benötigt?
  • Sie haben mich erwischt! Das ‚ handelt von allem, was ich über CAN-Bus weiß, und das war aus Wikipedia . Es ist eine Menge CAN-Bus-Dokumentation online; Die Bibliographie dieses Artikels ‚ ist ein guter Anfang.
  • 8 Byte ist die Größe der Datennutzlast eines Standard-Can-Frames. Sie benötigen also zwei Standard-Frames, um 16 Byte Informationen zu senden. Das neuere can-fd unterstützt 64-Byte-Datennutzdaten pro Frame.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.