Takže po 2 dnech pokusu o to nemohu dostat hlavu kolem.
Takže používám sběrnici CAN k přenosu dat akcelerometru a časových dat (funkce micros (), pokud za 71 minut budou výstup dat, která mohou být dlouhá bez znaménka), ale musím data odeslat jako bajty. podařilo se mi trochu posunout 16bitový int na 2 bajty, ale mám potíže s extrapolací této metody (přidám později) na použití longů. Mám potíže s porozuměním metodě unie, protože jsem nový při vytváření vlastních funkcí, tak, jak dosáhli byste to? Co nejjednodušší, prosím 🙂
Komentáře
- odečtete maximální bajt 3, který může být od celkového počtu, a od že odečíst maximální bajt 2 může být získat bajt 3. bajt 4 je jen maximální bajt 4 mínus počet mínus maximální bajt 3 +1.
Odpověď
Pomocí bitshifting a bitové a operátory.
Zde je příklad, který vám umožní extrahovat jednotlivé bajty vaší long
proměnné. Myslím, že by to mělo být straigtforward rozšířit na proměnné různé délky:
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); }
V závislosti na tom, jaké pořadí bajtů (velký nebo malý endian) se očekává, můžete před odesláním nebo po přijetí je třeba změnit pořadí bajtů.
Komentáře
- Velmi přímočarý a snadno pochopitelný princip tak děkuji, nicméně pod " rekonstruovaný " vytiskne pouze 5678?
- Zkopírovali jste úryvek kódu z mé odpovědi? Protože pokud spustím kód na svém nodemcu, dostanu správnou odpověď.
- Ano, kód jsem zkopíroval a vložil, přidal void setup (); a Serial.begin (9600); získat kód, aby běžel na mém arduino nano
- ve výchozím nastavení na 8bitovém AVR, na pravou stranu equals výchozí hodnoty int aritmetika, která je podepsána šestnáct bitů. Takže jsem vrhl pole na uint32_t ve smyčce. Nejste si jisti, zda je to nejefektivnější způsob, ale funguje to! Děkuji za vaši pomoc
- ano, správně. Když jsem zkoušel nodemcu, ' nemyslel jsem na arduino ovladač.
Odpovědět
Typ union
je podobný struct
kromě toho, že každý z členů prvku zaujímá stejná paměť. Pokud definujete struct
tak, že má 2 členy – jeden 4bajtový typ a jedno 4prvkové pole jednoho bajtového typu, můžete snadno odkazovat na stejná data jako celý čtyřbajtový prvek nebo po bajtech, jak si přejete.
union packed_long { long l; byte b[4]; };
Toto je typ, takže musíte deklarovat proměnnou jako tento typ:
packed_long mydata;
Nyní máte dva dílčí prvky mydata
: l
a b[]
.
Chcete-li uložit svoji hodnotu long
, napište do l
část:
mydata.l = myaccel.getY();
Přístup ke každému ze 4 bajtů:
byte1 = mydata.b[0]; byte2 = mydata.b[1]; byte3 = mydata.b[2]; byte4 = mydata.b[3];
Na přijímajícím konci vezmete každý ze 4 bajtů:
mydata.b[0] = canbus.read(); mydata.b[1] = canbus.read(); mydata.b[2] = canbus.read(); mydata.b[4] = canbus.read();
Dokud obdržíte bajty ve stejném pořadí ve kterém jste je poslali, nyní máte přístup ke své hodnotě long
v mydata.l
.
Skutečná velikost různých typů je v závislosti na kompilátoru a architektuře, takže můžete také chtít definovat svoji hodnotu jako proměnnou určité velikosti, abyste zajistili, že vždy pracujete s 32 bity: int32_t
(podepsané 32bitové celé číslo ) nebo uint32_t
(celé číslo bez znaménka).
Odpověď
Způsob, jak odeslat dlouhý, je maskování a odeslání bajtu LSB (standard CAN), poté posunutí další do pozice LSB, pro 4 bajty:
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 } //
Komentáře
- OK, takže CAN standard je LSB první. Jak víte o CAN, z toho, co mohu zjistit, že posílají 8 bajtový paket, jsou pouze jedna nebo dvě z těchto dat? Takže pro celkem 16 bajtů informací bude zapotřebí 8 paketů?
- Chytili jste mě! To ' se týká všeho, co vím o sběrnici CAN, a to z Wikipedie . Online je spousta dokumentace sběrnice CAN; tento článek ' s bibliografií je dobrým začátkem.
- 8 bajtů je velikost datového obsahu standardního can-frame. takže k odeslání 16 bajtů informací potřebujete dva standardní rámce. novější can-fd podporuje užitečné zatížení 64 bajtů dat na snímek.