convertir 32 bits de long en 4 octets et vice versa – Bus CAN

Donc, après 2 jours de tentative, je ne peux pas me faire une idée.

Jutilise donc le bus CAN pour transférer les données de laccéléromètre et les données de temps (la fonction micros () si moins de 71 minutes produira des données qui peuvent être non signées), mais je dois envoyer les données sous forme doctets. a réussi à décaler un bit int 16 bits en 2 octets, mais jai du mal à extrapoler cette méthode (ajoutera plus tard) à lutilisation de longs. Jai du mal à comprendre la méthode dunion car je suis nouveau dans la création de mes propres fonctions, alors, comment pourriez-vous accomplir cela? Aussi simple que possible sil vous plaît 🙂

Commentaires

  • vous soustrayez loctet maximum 3 peut être du total, et de qui soustraire loctet maximum 2 peut être pour obtenir loctet 3. Loctet 4 est juste loctet maximum 4 moins le nombre moins loctet maximum 3 +1.

Réponse

Vous pouvez réaliser ce que vous voulez en utilisant bitshifting et opérateurs bit -wise et .

Voici un exemple qui vous permet dextraire les octets individuels de votre variable long. Je pense quil devrait être plus simple de létendre à des variables de longueur différente:

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

En fonction de lordre des octets (grand ou petit boutiste) attendu, vous pourriez besoin de réorganiser les octets avant lenvoi ou après la réception.

Commentaires

  • Très simple et facile à comprendre le principe alors merci, cependant sous " reconstruit " il nimprime que 5678?
  • Avez-vous copié lextrait de code de ma réponse? Parce que si jexécute le code sur mon nodemcu, jobtiens la bonne réponse.
  • Oui, jai copié et collé le code, ajouté void setup (); et Serial.begin (9600); pour obtenir le code à exécuter sur mon arduino nano
  • par défaut sur un AVR 8 bits, à droite de légal par défaut, larithmétique int qui est signée seize bits. Jai donc casté le tableau en uint32_t dans la boucle. Je ne sais pas si cest le moyen le plus efficace, mais cela fonctionne! Merci pour votre aide
  • Oui, daccord. Je nai ' pas pensé au contrôleur arduino, quand jai essayé le nodemcu.

Réponse

Le type union est similaire à un struct sauf que chacun des membres de lélément occupe le même mémoire. Si vous définissez un struct de sorte quil ait 2 membres – un type 4 octets et un tableau 4 éléments dun type doctet unique, alors vous pouvez facilement vous référer aux mêmes données comme un élément entier de 4 octets, ou par octet comme vous le souhaitez.

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

Cest le type, vous devez donc déclarer la variable comme étant de ce type:

packed_long mydata; 

Maintenant, vous avez deux sous-éléments de mydata: l et b[].

Pour enregistrer votre valeur long, écrivez dans l part:

mydata.l = myaccel.getY(); 

Pour accéder à chacun des 4 octets:

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

À la réception, vous prenez chacun des 4 octets:

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

Tant que vous recevez les octets dans le même ordre dans lequel vous les avez envoyés, vous pouvez désormais accéder à votre long valeur dans mydata.l.

La taille réelle des différents types est dépendante du compilateur et de larchitecture, vous pouvez donc également définir votre valeur comme une variable de taille définie pour vous assurer que vous travaillez toujours avec 32 bits: int32_t (entier signé de 32 bits ) ou uint32_t (entier 32 bits non signé).

Réponse

Un moyen denvoyer un long est de masquer et denvoyer loctet LSB (norme CAN), puis de décaler le le suivant en position LSB, pour 4 octets:

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 } // 

Commentaires

  • OK, donc norme CAN est LSB en premier. Comme vous avez connaissance de CAN, daprès ce que je peux trouver, ils envoient un paquet de 8 octets, est-ce seulement un ou deux de ces données? Donc, pour un total de 16 octets dinformations, 8 paquets seraient-ils nécessaires?
  • Vous mavez attrapé! Voilà ' tout ce que je sais sur le bus CAN, et cela provient de Wikipédia . Il y a beaucoup de documentation sur le bus CAN en ligne; la bibliographie de cet article ' est un bon début.
  • 8 octets est la taille de la charge de données dun can-frame standard. vous avez donc besoin de deux trames standard pour envoyer 16 octets dinformations. le plus récent can-fd prend en charge 64 octets de données utiles par image.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *