converteer 32 bit lang naar 4 bytes en weer terug – CAN Bus

Dus na 2 dagen proberen kan ik er niet omheen.

Dus ik gebruik CAN-bus om versnellingsmetergegevens en tijdgegevens over te dragen (de micros () -functie als minder dan 71 minuten gegevens zullen uitvoeren die een niet-ondertekende lengte kunnen zijn), maar ik moet de gegevens als bytes verzenden. Ik heb slaagde erin om een 16-bit int in 2 bytes te verschuiven, maar ik heb problemen met het extrapoleren van die methode (zal later worden toegevoegd) naar het gebruik van longs. Ik heb problemen met het begrijpen van de union-methode omdat ik nieuw ben in het maken van mijn eigen functies, dus willen jullie dit bereiken? Zo simpel mogelijk 🙂

Reacties

  • je trekt de maximale byte 3 af van het totaal, en van dat aftrekken van de maximale byte 2 kan zijn om byte 3 te krijgen. byte 4 is gewoon max byte 4 minus getal minus max byte 3 +1.

Antwoord

U kunt bereiken wat u wilt door bitshifting en bit-wise en operators.

Hier is een voorbeeld waarmee u de individuele bytes van uw long variabele. Ik denk dat het eenvoudig moet zijn om het uit te breiden naar variabelen van verschillende lengte:

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

Afhankelijk van welke bytevolgorde (groot of klein endian) wordt verwacht, zou je moeten de bytes opnieuw ordenen voordat ze worden verzonden of na ontvangst.

Reacties

  • Zeer eenvoudig en gemakkelijk om het principe te begrijpen, dus bedankt, maar onder " gereconstrueerd " het drukt alleen 5678 af?
  • Heb je het codefragment uit mijn antwoord gekopieerd? Omdat als ik de code op mijn nodemcu uitvoer, ik het juiste antwoord krijg.
  • Ja, ik heb de code gekopieerd en geplakt, void setup () toegevoegd; en Serial.begin (9600); om de code te laten draaien op mijn arduino nano
  • standaard op een 8 bit AVR, aan de rechterkant van de equals standaard naar int arithmetic die zestien bit is ondertekend. Dus ik cast de array naar een uint32_t in de lus. Niet zeker of dat de meest efficiënte manier is, maar het werkt! Bedankt voor je hulp
  • ja juist. Ik heb ' niet aan de arduino-controller gedacht toen ik de nodemcu probeerde.

Answer

Het union type is vergelijkbaar met een struct behalve dat elk van de leden van het element de hetzelfde geheugen. Als u een struct zo definieert dat deze twee leden heeft – een 4-byte type en een 4-element array van een enkel byte type, dan kunt u gemakkelijk naar dezelfde gegevens verwijzen als een geheel 4-byte-element, of byte-wijs zoals u wenst.

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

Dit is het type, dus u moet de variabele declareren als zijnde van dat type:

packed_long mydata; 

Nu heb je twee subelementen van mydata: l en b[].

Om uw long waarde op te slaan, schrijft u naar de l deel:

mydata.l = myaccel.getY(); 

Om toegang te krijgen tot elk van de 4 bytes:

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

Aan de ontvangende kant neem je elk van de 4 bytes:

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

Zolang je de bytes in dezelfde volgorde ontvangt waarin u ze heeft verzonden, heeft u nu toegang tot uw long -waarde in mydata.l.

De werkelijke grootte van verschillende typen is afhankelijk van de compiler en architectuur, dus misschien wilt u uw waarde ook definiëren als een variabele met een bepaalde grootte om ervoor te zorgen dat u altijd met 32 bits werkt: int32_t (32-bits geheel getal met teken ) of uint32_t (32-bits geheel getal zonder teken).

Answer

Een manier om een long te verzenden is door af te schermen en de LSB-byte te verzenden (CAN-standaard), en vervolgens de volgende in LSB-positie, voor 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 } // 

Reacties

  • OK, dus CAN standaard is LSB eerst. Zoals u weet van CAN, van wat ik kan vinden, sturen ze een pakket van 8 bytes, zijn slechts een of twee daarvan de gegevens? Dus voor een totaal van 16 bytes aan informatie, zouden er 8 pakketten nodig zijn?
  • Je betrapte me! Dat ' is ongeveer alles wat ik weet over CAN-bus, en dat was van Wikipedia . Er is veel CAN-bus-documentatie online; dat artikel ' s bibliografie is een goed begin.
  • 8 byte is de grootte van de gegevenspayload van een standaard can-frame. je hebt dus twee standaardframes nodig om 16 byte aan informatie te verzenden. de nieuwere can-fd ondersteunt 64 byte data payload per frame.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *