Scomporre e ricomporre unsigned long

Salve a tutti,
mi servirebbe qualche suggerimento su come convertire, quindi scomporre, un unsigned long in un uint8_t, per poi ricomporlo. Devo usare la libreria TinyWireS per trasmettere un unsigned long via i2C a un arduino uno. Mi potreste dare suggerimenti? Ho trovato qualcosa in giro, ma niente di funzionante. Come potrei fare?

Grazie, Giovicavalla

unsigned long l = 0x01020304;

byte b1 = l & 0xFF;
byte b2 = (l >> 8) & 0xFF;
byte b3 = (l >> 16) & 0xFF;
byte b4 = (l >> 24) & 0xFF;

Riesci a ricomporlo da solo?

Ciao,
mmm.. :o non credo, non riuscivo a capire come ricomporlo..

ricompongo

unsigned long l = 0;
l |= (unsigned long)(b1) ;
l |= (unsigned long)(b2) << 8;
l |= (unsigned long)(b3) << 16;
l |= (unsigned long)(b4) << 24;

@sukkopera correggi il tuo codice.

Ciao a tutti,
grazie mille per le risposte così tempestive, ma proprio non riesco a farlo andare. Posto il codice che uso per mandare e ricevere, potete dargli un’occhiata?

Questo è quello per mandare

volatile byte SendCount = 0;
volatile uint8_t sendByte;

void requestEvent() {

  SendCount++;
  switch (SendCount)
  {
    case 1:
      sendByte = Freq & 0xFF;
      break;
    case 2:
      sendByte = Freq >> 8;
      break;
    case 3:
      sendByte = Freq >> 16;
      break;
    case 4:
      sendByte = Freq >> 24;
      SendCount = 0;
      break;
  }

  
  TinyWireS.send(sendByte);

}

Questo è quello per ricevere:

 for(i = 0; i < N_STRING; i++) {
    Wire.requestFrom(I2CAddress[i],4);
    while(Wire.available()) {
      for (int j = 0; j < 4; j++) {
      frequencyString[1] = (unsigned long) Wire.read() << j * 8;
      
      }
//      frequencyString[i] = Wire.read(); //8.464
//      Serial.println(Wire.read());
    }
    delay(10);
  }

Ciao, Giovicavalla

Ti sei perso un pezzo nel codice della scomposizione... l'and con la mask in particolare.

Ciao,
Non va comunque, ecco il codice modificato:

void requestEvent() {

  SendCount++;
  switch (SendCount)
  {
    case 1:
      sendByte = (Freq) & 0xFF;
      break;
    case 2:
      sendByte = (Freq >> 8) & 0xFF;
      break;
    case 3:
      sendByte = (Freq >> 16) & 0xFF;
      break;
    case 4:
      sendByte = (Freq >> 24) & 0xFF;
      SendCount = 0;
      break;
  }

  
  TinyWireS.send(sendByte);

}

Come posso fare?

Ciao, Giovicavalla

sendCount è inizializzato a 0 all'inizio?

Ciao,
si, sendCount è inizializzato a zero nella dichiarazione. Si vede nel primo codice che ho mandato.

Ciao, Giovicavalla

Ciao,
nessuna idea sul perché non funga?

frequencyString[1] = (unsigned long) Wire.read() << j * 8;

Perché [1]? Non dovrebbe essere [ i ]? A parte questo, comunque così non metti insieme i byte, ma li sovrascrivi l’uno con l’altro. Devi fare:

frequencyString[1] |= (unsigned long) Wire.read() << j * 8;

E devi anche inizializzarlo a 0 prima di mettergli dentro il primo byte.

Ciao

mi permetto di suggerire un altro modo per accedere ai bytes di un unsigned long.

Si tratta di utilizzare una union che è un modo del linguaggio C per indicare al compilatore di utilizzare la medesima area di memoria per memorizzare variabile diverse.

Un esempio:

union Data
{
  unsigned long l;
  byte b[4];
};

void setup()
{
  Serial.begin(9600);
  
  Data d;
  
  d.l = 1234567890;
  
  Serial.print(d.b[0], DEC);
  Serial.print(" ");
  Serial.print(d.b[1], DEC);
  Serial.print(" ");
  Serial.print(d.b[2], DEC);
  Serial.print(" ");
  Serial.print(d.b[3], DEC);
  Serial.println("");
  
  d.b[0] = 210;
  d.b[1] = 2;
  d.b[2] = 150;
  d.b[3] = 73;
  
  Serial.print(d.l, DEC);
}

void loop()
{
}

La union Data dice al compilatore di memorizzare nella stessa area di memoria sia un unsigned long sia un array di 4 bytes. Questo significa che se inizializziamo il long poi possiamo vedere i suoi quattro bytes nell’array. Viceversa se inizializiamo i 4 bytes, possiamo poi accedere al long.

Nella setup ho fatto un piccolo esempio che mostra sulla seriale entrambe le “conversioni”.

Ciao a tutti,
vi stresso ancora, ma per un long vale ugualmente il codice di prima oppure si deve cambiare qualcosa?

Ciao, Giovicavalla

È uguale per tutti i dati lunghi 4 byte. Unsigned cambia solo l'interpretazione, non la lunghezza.

Ciao,
scusa ancora lo stress, ma non riesco proprio, cioè, ti spiego. Ho dovuto optare per una comunicazione tra Uno e Uno, quindi ho eliminato l'attiny, il problema però resta perché devo usare il protocollo I2C (cosa che non avevo mai fatto). Ora ho cambiato il sketch, ma ho lasciato lo stesso sistema di conversione e invio/ricezione, con l'attiny andava, con l'atmega no! Non ho fatto nulla di diverso però! Cosa può essere successo?

Ciao, Giovicavalla

Posta gli sketch interi.

Ciao,
scusate per la mia lunga assenza, ho risolto con le Union, senza troppi problemi. Se volete posto il codice per usarle. Grazie di tutto!

Ciao, Giovicavalla