przekonwertuj długość 32-bitową na 4 bajty iz powrotem – CAN Bus

Więc po 2 dniach próby nie mogę tego obejść.

Więc używam magistrali CAN do przesyłania danych akcelerometru i danych czasu (funkcja micros (), jeśli poniżej 71 minut wyprowadzi dane, które mogą mieć długość bez znaku), jednak muszę wysłać dane jako bajty. udało mi się przesunąć nieco 16-bitową liczbę int do 2 bajtów, ale mam problem z ekstrapolacją tej metody (dodam ją później) na użycie długich. Mam problemy ze zrozumieniem metody unii, ponieważ jestem nowy w tworzeniu własnych funkcji, więc jak czy moglibyście to osiągnąć? Tak prosto, jak to tylko możliwe 🙂

Komentarze

  • odejmujesz maksymalny bajt 3 od sumy, a od które odejmują maksymalny bajt 2, aby uzyskać bajt 3. bajt 4 to po prostu maksymalny bajt 4 minus liczba minus maksymalny bajt 3 +1.

Odpowiedź

Możesz osiągnąć to, co chcesz, używając bitshifting i bit-mądre i operatory.

Oto przykład, który pozwala wyodrębnić poszczególne bajty zmiennej long. Myślę, że rozszerzenie go na zmienne o różnej długości powinno być proste:

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

W zależności od oczekiwanej kolejności bajtów (duży lub mały endian), możesz trzeba zmienić kolejność bajtów przed wysłaniem lub po odebraniu.

Komentarze

  • Bardzo prosta i łatwa do zrozumienia zasada, więc dziękuję, jednak pod " zrekonstruowano " drukuje tylko 5678?
  • Czy skopiowałeś fragment kodu z mojej odpowiedzi? Ponieważ jeśli uruchomię kod na moim nodemcu, otrzymam właściwą odpowiedź.
  • Tak, skopiowałem i wkleiłem kod, dodałem void setup (); i Serial.begin (9600); aby kod działał na moim arduino nano
  • domyślnie na 8-bitowym AVR, po prawej stronie równa się domyślnie arytmetyka int, która jest podpisana szesnastobitowo. Więc rzuciłem tablicę na uint32_t w pętli. Nie jestem pewien, czy to najbardziej efektywny sposób, ale działa! Dziękuję za pomoc
  • tak dobrze. Nie myślałem ' o kontrolerze arduino, kiedy próbowałem na nodemcu.

Odpowiedz

Typ union jest podobny do struct z tą różnicą, że każdy z członków elementu zajmuje ta sama pamięć. Jeśli zdefiniujesz struct tak, aby miał 2 elementy – jeden typ 4-bajtowy i jedną 4-elementową tablicę typu jednobajtowego, możesz łatwo odwołać się do tych samych danych jako całość 4-bajtowego elementu lub według własnego uznania.

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

To jest typ, więc musisz zadeklarować zmienną jako ten typ:

packed_long mydata; 

Teraz masz dwa podelementy mydata: l i b[].

Aby zapisać swoją wartość long, napisz do l część:

mydata.l = myaccel.getY(); 

Aby uzyskać dostęp do każdego z 4 bajtów:

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

Po stronie odbiorczej bierzesz każdy z 4 bajtów:

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

O ile otrzymujesz bajty w tej samej kolejności w którym je wysłałeś, możesz teraz uzyskać dostęp do swojej long wartości w mydata.l.

Rzeczywisty rozmiar różnych typy jest zależy od kompilatora i architektury, więc możesz również chcieć zdefiniować swoją wartość jako zmienną o określonym rozmiarze, aby mieć pewność, że zawsze pracujesz z 32-bitowymi bitami: int32_t (32-bitowa liczba całkowita ze znakiem ) lub uint32_t (32-bitowa liczba całkowita bez znaku).

Odpowiedź

Sposobem wysłania długiego jest zamaskowanie i wysłanie bajtu LSB (standard CAN), a następnie przesunięcie następny w pozycji LSB, dla 4 bajtów:

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

Komentarze

  • OK, więc standard CAN jest najpierw LSB. Skoro znasz CAN, z tego, co mogę znaleźć, wysyłają pakiet 8-bajtowy, czy tylko jeden lub dwa z nich to dane? Czy więc w sumie 16 bajtów informacji będzie potrzebnych 8 pakietów?
  • Złapałeś mnie! To ' wszystko, co wiem o magistrali CAN, a to pochodzi z Wikipedii . W Internecie jest dużo dokumentacji dotyczącej magistrali CAN; bibliografia tego artykułu ' to dobry początek.
  • 8 bajtów to rozmiar ładunku danych standardowej ramki can. więc potrzebujesz dwóch standardowych ramek do przesłania 16 bajtów informacji. nowszy can-fd obsługuje 64 bajty danych na ramkę.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *