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.