konverter 32 bit lang til 4 byte og tilbake igjen – CAN Bus

Så etter 2 dagers forsøk på dette kan jeg ikke få hodet rundt det.

Så jeg bruker CAN-buss til å overføre akselerometerdata og tidsdata (mikrofonene () fungerer hvis under 71 minutter vil sende ut data som kan være en usignert lang), men jeg må sende dataene som byte. Jeg har klarte å bit skifte en 16-bit int til 2 byte, men jeg har problemer med å ekstrapolere den metoden (vil legge til senere) til å bruke longs. Jeg har problemer med å forstå unionmetoden ettersom jeg er ny i å lage mine egne funksjoner, så hvordan ville dere oppnå dette? Så enkelt som mulig 🙂 🙂

Kommentarer

  • du trekker maks maks. byte 3 kan være fra totalen, og fra som trekker maksimal byte 2 kan være å få byte 3. byte 4 er bare maks byte 4 minus antall minus maks byte 3 +1.

Svar

Du kan oppnå det du ønsker ved å bruke bitshifting og bitvis og operatorer.

Her er et eksempel som lar deg trekke ut de individuelle byte til long -variabelen. Jeg synes det burde være lett å utvide den til variabler med ulik lengde:

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

Avhengig av hvilken bytebestilling (stor eller liten endian) som forventes, kan du trenger å omorganisere byte før du sender eller etter mottak.

Kommentarer

  • Veldig grei og lett å forstå prinsippet så takk, men under " rekonstruert " den skriver bare ut 5678?
  • Kopierte du kodebiten fra svaret mitt? For hvis jeg kjører koden på min nodemcu, får jeg riktig svar.
  • Ja, jeg kopierte og limte inn koden, la til tomt oppsett (); og Serial.begin (9600); for å få koden til å kjøre på min arduino nano
  • som standard på en 8-biters AVR, til høyre for den liknende er standard til aritmetikk som er signert seksten bit. Så jeg kastet matrisen til en uint32_t i løkken. Usikker på om det er den mest effektive måten, men det fungerer! Takk for hjelpen
  • ja ikke sant. Jeg tenkte ikke ' på arduino-kontrolleren, da jeg prøvde på nodemcu.

Svar

union typen ligner på en struct bortsett fra at hvert av elementene i elementet okkuperer samme minne. Hvis du definerer en struct slik at den har to medlemmer – en 4-byte-type og en 4-element-matrise av en enkelt byte-type, kan du enkelt referere til de samme dataene som et hele 4-byte-element, eller byte-klokt som du ønsker.

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

Dette er typen, så du må erklære at variabelen er av den typen:

packed_long mydata; 

Nå har du to underelementer av mydata: l og b[].

For å lagre long -verdien, skriv til l del:

mydata.l = myaccel.getY(); 

For å få tilgang til hvert av de 4 byte:

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

På mottakersiden tar du hvert av de 4 byte:

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

Så lenge du mottar byte i samme rekkefølge der du sendte dem, kan du nå få tilgang til long -verdien i mydata.l.

Den faktiske størrelsen på forskjellige typer er avhengig av kompilatoren og arkitekturen, så det kan også være lurt å definere verdien din som en variabel i bestemt størrelse for å sikre at du alltid jobber med 32 bits: int32_t (signert 32-biters heltall ) eller uint32_t (usignert 32-biters heltall).

Svar

En måte å sende en lang er å maskere av og sende LSB-byte (CAN-standard), og deretter skifte neste i LSB-posisjon, for 4 byte:

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å KAN standard er LSB først. Som du har kunnskap om CAN, er det bare en eller to av dataene som jeg kan finne at de sender en 8 byte-pakke? Så for totalt 16 byte informasjon, ville det være behov for 8 pakker?
  • Du fanget meg! At ' handler om alt jeg vet om CAN-buss, og det var fra Wikipedia . Det er mye CAN-bussdokumentasjon på nettet; at artikkelen ' s bibliografi er god start.
  • 8 byte er størrelsen på datanytten til en standard bokseramme. så du trenger to standardrammer for å sende 16 byte informasjon. den nyere can-fd støtter 64 byte data nyttelast per ramme.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *