konverter 32 bit lang til 4 bytes og tilbage igen – CAN Bus

Så efter 2 dages forsøg på dette kan jeg ikke få hovedet rundt.

Så jeg bruger CAN-bus til at overføre accelerometerdata og tidsdata (mikrofonerne () fungerer, hvis under 71 minutter udsender data, der kan være en usigneret lang), men jeg er nødt til at sende dataene som bytes. Jeg har formået at skifte en 16-bit int til 2 byte, men jeg har problemer med at ekstrapolere den metode (tilføjes senere) til at bruge længder. Jeg har problemer med at forstå unionmetoden, da jeg er ny til at oprette mine egne funktioner, så hvordan ville I fyre opnå dette? Så simpelt som muligt 🙂

Kommentarer

  • trækker du den maksimale byte 3 kan være fra det samlede antal og fra at trække den maksimale byte 2 kan være at få byte 3. byte 4 er bare maks. byte 4 minus antal minus maks. byte 3 +1.

Svar

Du kan opnå det, du ønsker, ved at bruge bitshifting og bitvise og operatorer.

Her er et eksempel, der giver dig mulighed for at udtrække de individuelle bytes i din long -variabel. Jeg synes, det skal være ligeud at udvide det til variabler med forskellig længde:

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); } 

Afhængigt af hvilken bytebestilling (stor eller lille endian) der forventes, kan du muligvis har brug for at ændre rækkefølgen af bytes, før de sendes eller efter modtagelsen.

Kommentarer

  • Meget ligetil og let at forstå princippet så tak, dog under " rekonstrueret " udskriver det kun 5678?
  • Kopierede du kodestykket fra mit svar? For hvis jeg kører koden på min nodemcu, får jeg det rigtige svar.
  • Ja, jeg kopierede og indsatte koden, tilføjede ugyldig opsætning (); og Serial.begin (9600); for at få koden til at køre på min arduino nano
  • som standard på en 8 bit AVR, til højre for ligen er standardindstillingerne til aritmetik, der er signeret seksten bit. Så jeg kastede arrayet til en uint32_t i loop. Usikker på, om det er den mest effektive måde, men det fungerer! Tak for din hjælp
  • ja rigtigt. Jeg tænkte ikke ' på arduino-controlleren, da jeg prøvede på nodemcu.

Svar

union typen ligner en struct bortset fra at hver af elementerne i elementet besætter samme hukommelse. Hvis du definerer en struct, så den har 2 medlemmer – en 4-byte-type og en 4-element-array af en enkelt byte-type, så kan du nemt henvise til de samme data som et hele 4-byte-element, eller byte-vis, som du ønsker.

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

Dette er typen, så du skal erklære variablen for at være af den type:

packed_long mydata; 

Nu har du to underelementer af mydata: l og b[].

For at gemme din long -værdi, skriv til l del:

mydata.l = myaccel.getY(); 

For at få adgang til hver af de 4 bytes:

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

I den modtagende ende tager du hver af de 4 bytes:

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

Så længe du modtager byte i samme rækkefølge hvor du sendte dem, kan du nu få adgang til din long værdi i mydata.l.

Den faktiske størrelse af forskellige typer er afhængig af kompilatoren og arkitekturen, så du kan også ønske at definere din værdi som en bestemt størrelse variabel for at sikre, at du altid arbejder med 32 bit: int32_t (signeret 32-bit heltal ) eller uint32_t (usigneret 32-bit heltal).

Svar

En måde at sende en lang er at maskere og sende LSB-byte (CAN-standard) og derefter skifte næste i LSB-position i 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 } // 

Kommentarer

  • OK, så CAN standard er LSB først. Som du har kendskab til CAN, er det kun en eller to af dataene, hvad jeg kan finde, at de sender en 8 byte-pakke? Så for i alt 16 byte information, ville der være brug for 8 pakker?
  • Du fangede mig! At ' handler om alt, hvad jeg kender til CAN-bus, og det var fra Wikipedia . Der er en masse CAN-busdokumentation online; at artiklen ' s bibliografi er en god start.
  • 8 byte er størrelsen på datanyttelasten for en standard dåseramme. så du har brug for to standardrammer til at sende 16 byte information. den nyere can-fd understøtter 64 byte data nyttelast pr. frame.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *