konvertera 32 bitar långa till 4 byte och tillbaka igen – CAN Bus

Så efter två dagars försök kan jag inte få mitt huvud runt det.

Så jag använder CAN-buss för att överföra accelerometerdata och tidsdata (micros () fungerar om under 71 minuter kommer att mata ut data som kan vara en osignerad lång), men jag måste skicka data som byte. Jag har lyckades bitförskjuta en 16-bitars int till 2 byte men jag har problem med att extrapolera den metoden (kommer att läggas till senare) till att använda longs. Jag har problem med att förstå unionsmetoden eftersom jag är ny på att skapa mina egna funktioner, så hur skulle ni kunna åstadkomma detta? Så enkelt som möjligt 🙂

Kommentarer

  • subtraherar du maximalt byte 3 kan vara från summan, och från som subtraherar maximal byte 2 kan vara att få byte 3. byte 4 är bara max byte 4 minus antal minus max byte 3 +1.

Svar

Du kan uppnå vad du vill med bitshifting och bitvis och operatorer.

Här är ett exempel som låter dig extrahera de enskilda byten i din long -variabel. Jag tycker att det borde vara enkelt att utvidga det till variabler med olika längd:

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

Beroende på vilken bytebeställning (stor eller liten endian) förväntas kan du måste ordna om byten innan du skickar eller efter att ha mottagit.

Kommentarer

  • Mycket enkelt och lätt att förstå principen så tack, dock under " rekonstruerad " skrivs det bara ut 5678?
  • Kopierade du kodavsnittet från mitt svar? För om jag kör koden på min nodemcu får jag rätt svar.
  • Ja, jag kopierade och klistrade in koden, lade till ogiltig installation (); och Serial.begin (9600); för att få koden att köras på min arduino nano
  • som standard på en 8-bitars AVR, till höger om motsvarar standardvärdena till aritmetik som är signerad sexton bitar. Så jag kastade arrayen till en uint32_t i loop. Osäker på om det är det mest effektiva sättet, men det fungerar! Tack för din hjälp
  • ja rätt. Jag tänkte inte ' på arduino-styrenheten när jag försökte på nodemcu.

Svar

union -typen liknar en struct förutom att var och en av elementen i elementet upptar samma minne. Om du definierar en struct så att den har två medlemmar – en 4-byte-typ och en 4-elements array av en enda byte-typ, kan du enkelt hänvisa till samma data som ett helt 4-byte-element, eller byte-visat som du vill.

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

Det här är typen, så du måste förklara variabeln att den är den typen:

packed_long mydata; 

Nu har du två underelement av mydata: l och b[].

För att spara ditt long -värde, skriv till l del:

mydata.l = myaccel.getY(); 

För att komma åt var och en av de 4 bytes:

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

I den mottagande änden tar du vart och ett av de fyra 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 får bytes i samma ordning där du skickade dem kan du nu komma åt ditt long värde i mydata.l.

Den faktiska storleken på olika typer är beroende på kompilatorn och arkitekturen, så du kanske också vill definiera ditt värde som en bestämd storlek för att säkerställa att du alltid arbetar med 32 bitar: int32_t (signerad 32-bitars heltal ) eller uint32_t (osignerat 32-bitars heltal).

Svar

Ett sätt att skicka en lång är att maskera och skicka LSB-byte (CAN-standard) och sedan skifta nästa i LSB-position, för 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 är LSB först. Eftersom du har kunskap om CAN, från vad jag kan hitta skickar de ett 8 byte paket, är bara en eller två av dessa uppgifterna? Så för totalt 16 byte information, behövs 8 paket?
  • Du fångade mig! Att ' handlar om allt jag vet om CAN-buss, och det var från Wikipedia . Det finns mycket CAN-bussdokumentation online; den artikeln ' s bibliografi är en bra start.
  • 8 byte är storleken på datanyttolasten för en standard burkram. så du behöver två standardramar för att skicka 16 byte information. den nyare can-fd stöder 64 byte data nyttolast per ram.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *