Deci, după 2 zile încercând acest lucru, nu pot să-mi învârt capul.
Deci, folosesc magistrala CAN pentru a transfera date de accelerometru și date de timp (funcția micros () dacă sub 71 de minute va ieși date care pot fi lungi nesemnate), totuși trebuie să trimit datele ca octeți. Am am reușit să schimb un bit de 16 biți în 2 octeți, dar am probleme cu extrapolarea acelei metode (se va adăuga mai târziu) la utilizarea de lungimi. Am probleme cu înțelegerea metodei de unire, deoarece sunt nou în crearea propriilor funcții ați putea realiza acest lucru? Cât de simplu este posibil, vă rog 🙂
Comentarii
- scădeți octetul maxim 3 care poate fi din total și din care scade octetul maxim 2 poate fi obținerea octetului 3. octetul 4 este doar octetul maxim 4 minus numărul minus octetul maxim 3 +1.
Răspuns
Puteți realiza ceea ce doriți utilizând bitshifting și bit-wise și operatori.
Iată un exemplu care vă permite să extrageți octeții individuali ai variabilei dvs. long
. Cred că ar trebui să fie rapid să-l extindem la variabile de lungime diferită:
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); }
În funcție de ordinea octeților (mare sau mic endian) este de așteptat, s-ar putea trebuie să reordonați octeții înainte de a trimite sau de a primi.
Comentarii
- Foarte simplu și ușor de înțeles principiul atât de mulțumitor, totuși sub " reconstruit " tipărește doar 5678?
- Ați copiat fragmentul de cod din răspunsul meu? Pentru că, dacă execut codul pe nodemcu, primesc răspunsul corect.
- Da, am copiat și lipit codul, am adăugat setarea nulă (); și Serial.begin (9600); pentru a obține codul să ruleze pe arduino nano meu
- în mod implicit pe un AVR pe 8 biți, în partea dreaptă a valorii implicite este aritmetica int care este semnată pe șaisprezece biți. Așa că am aruncat matricea la uint32_t în buclă. Nu sunt sigur dacă acesta este cel mai eficient mod, dar funcționează! Vă mulțumim pentru ajutor
- da corect. Nu m-am gândit la ' la controlerul arduino, când am încercat nodemcu.
Răspuns
Tipul union
este similar cu un struct
, cu excepția faptului că fiecare dintre membrii elementului ocupă aceeași amintire. Dacă definiți un struct
astfel încât acesta să aibă 2 membri – un tip de 4 octeți și o matrice de 4 elemente dintr-un singur tip de octeți, atunci puteți consulta cu ușurință aceleași date ca un întreg element de 4 octeți, sau în funcție de octeți, după cum doriți.
union packed_long { long l; byte b[4]; };
Acesta este tipul, deci trebuie să declarați că variabila este de acel tip:
packed_long mydata;
Acum, aveți două subelemente din mydata
: l
și b[]
.
Pentru a salva valoarea long
, scrieți la l
parte:
mydata.l = myaccel.getY();
Pentru a accesa fiecare dintre cei 4 octeți:
byte1 = mydata.b[0]; byte2 = mydata.b[1]; byte3 = mydata.b[2]; byte4 = mydata.b[3];
La capătul de primire, luați fiecare dintre cei 4 octeți:
mydata.b[0] = canbus.read(); mydata.b[1] = canbus.read(); mydata.b[2] = canbus.read(); mydata.b[4] = canbus.read();
Atâta timp cât primiți octeții în aceeași ordine în care le-ați trimis, acum puteți accesa valoarea long
în mydata.l
.
Dimensiunea reală a diferitelor tipuri este dependent de compilator și arhitectură, deci poate doriți să vă definiți valoarea ca o variabilă de dimensiuni definite pentru a vă asigura că lucrați întotdeauna cu 32 de biți: int32_t
(întreg semnat pe 32 de biți ) sau uint32_t
(întreg nesemnat pe 32 de biți).
Răspuns
O modalitate de a trimite un lung este să mascați și să trimiteți octetul LSB (standard CAN), apoi să schimbați următorul în poziția LSB, pentru 4 octeți:
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 } //
Comentarii
- OK, deci CAN standard este primul LSB. După cum aveți cunoștințe despre CAN, din ceea ce pot găsi trimit un pachet de 8 octeți, sunt doar unul sau doi dintre aceștia datele? Deci, pentru un total de 16 octeți de informații, ar fi necesare 8 pachete?
- M-ați prins! Asta ' despre tot ceea ce știu despre autobuzul CAN și asta a fost de la Wikipedia . Există o mulțime de documentații despre autobuzul CAN online; bibliografia respectivă a articolului ' este un început bun.
- 8 octeți reprezintă dimensiunea încărcăturii utile a datelor dintr-un cadru standard pentru can. deci aveți nevoie de două cadre standard pentru a trimite 16 octeți de informații. noul can-fd acceptă încărcarea utilă a datelor pe 64 de octeți pe cadru.