converti 32 bit di lunghezza a 4 byte e viceversa – CAN Bus

Quindi, dopo 2 giorni di tentativi, non riesco “a capirlo.

Quindi sto usando il bus CAN per trasferire i dati dellaccelerometro e i dati temporali (la funzione micros () se meno di 71 minuti produrrà dati che possono essere lunghi senza segno), tuttavia devo inviare i dati come byte. sono riuscito a spostare un bit int a 16 bit in 2 byte ma ho problemi a estrapolare quel metodo (aggiungerò in seguito) per usare i long. Ho problemi a capire il metodo di unione perché sono nuovo nella creazione delle mie funzioni, quindi, come ragazzi, riuscireste a farlo? Il più semplice possibile per favore 🙂

Commenti

  • sottraete il byte 3 massimo che può essere dal totale e da che sottrae il byte massimo 2 può essere per ottenere il byte 3. byte 4 è solo il byte massimo 4 meno il numero meno il byte massimo 3 +1.

Risposta

Puoi ottenere ciò che desideri utilizzando bitshifting e bit-wise e operatori.

Ecco un esempio che ti consente di estrarre i singoli byte della variabile long. Penso che dovrebbe essere semplice estenderlo a variabili di lunghezza diversa:

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

A seconda di quale ordinamento dei byte (big o little endian) è previsto, potresti è necessario riordinare i byte prima di inviarli o dopo averli ricevuti.

Commenti

  • Il principio è molto semplice e di facile comprensione, quindi grazie, comunque sotto " ricostruito " stampa solo 5678?
  • Hai copiato lo snippet di codice dalla mia risposta? Perché se eseguo il codice sul mio nodemcu ottengo la risposta giusta.
  • Sì, ho copiato e incollato il codice, aggiunto void setup (); e Serial.begin (9600); per fare in modo che il codice funzioni sul mio arduino nano
  • di default su un AVR a 8 bit, a destra dellequals il valore predefinito è int aritmetica che è firmato a sedici bit. Quindi ho lanciato larray su un uint32_t nel ciclo. Non sono sicuro che sia il modo più efficiente, ma funziona! Grazie per il tuo aiuto
  • sì, giusto. Non ' pensavo al controller arduino, quando ho provato il nodemcu.

Risposta

Il tipo union è simile a un struct tranne per il fatto che ciascuno dei membri dellelemento occupa il stessa memoria. Se definisci un struct in modo che abbia 2 membri: un tipo a 4 byte e un array a 4 elementi di un tipo a byte singolo, puoi facilmente fare riferimento agli stessi dati come un intero elemento di 4 byte, o per byte come desideri.

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

Questo è il tipo, quindi devi dichiarare la variabile come di quel tipo:

packed_long mydata; 

Ora hai due sottoelementi di mydata: l e b[].

Per salvare il valore long, scrivi in l parte:

mydata.l = myaccel.getY(); 

Per accedere a ciascuno dei 4 byte:

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

Allestremità ricevente, prendi ciascuno dei 4 byte:

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

Finché ricevi i byte nello stesso ordine in cui li hai inviati, ora puoi accedere al tuo valore long in mydata.l.

La dimensione effettiva dei diversi tipi è dipende dal compilatore e dallarchitettura, quindi potresti anche voler definire il tuo valore come una variabile di dimensioni definite per assicurarti di lavorare sempre con 32 bit: int32_t (numero intero con segno a 32 bit ) o uint32_t (numero intero senza segno a 32 bit).

Risposta

Un modo per inviare un messaggio lungo è mascherare e inviare il byte LSB (standard CAN), quindi spostare il il successivo nella posizione LSB, per 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 } // 

Commenti

  • OK, quindi CAN standard è prima LSB. Come sapete di CAN, da quello che posso trovare inviano un pacchetto di 8 byte, è solo uno o due di questi dati? Quindi per un totale di 16 byte di informazioni, sarebbero necessari 8 pacchetti?
  • Mi hai beccato! Questo è ' su tutto ciò che so sul bus CAN, ed era da Wikipedia . In linea è disponibile molta documentazione sul bus CAN; la bibliografia di questo articolo ' è un buon inizio.
  • 8 byte è la dimensione del payload dei dati di un can-frame standard. quindi sono necessari due frame standard per inviare 16 byte di informazioni. il più recente can-fd supporta un payload di dati a 64 byte per frame.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *