converter 32 bits em 4 bytes e vice-versa – CAN Bus

Portanto, após 2 dias tentando fazer isso, não consigo entender.

Estou usando o barramento CAN para transferir dados do acelerômetro e dados de tempo (a função micros (), se menos de 71 minutos, produzirá dados que podem ser longos sem sinal), no entanto, tenho que enviar os dados como bytes. consegui mudar o bit de um int de 16 bits para 2 bytes, mas estou tendo problemas para extrapolar esse método (adicionarei mais tarde) para usar longos. Estou tendo problemas para entender o método de união, pois sou novo na criação de minhas próprias funções, então, como vocês fariam isso? O mais simples possível, por favor 🙂

Comentários

  • você subtrai o byte máximo que 3 pode ser do total e de que subtrair o byte 2 máximo pode ser para obter o byte 3. o byte 4 é apenas o byte máximo 4 menos o número menos o byte máximo 3 +1.

Resposta

Você pode conseguir o que deseja usando bitshifting e operadores bit a bit e .

Aqui está um exemplo que permite extrair os bytes individuais de sua variável long. Acho que deveria ser direto estendê-lo para variáveis de comprimento diferente:

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

Dependendo de qual ordem de bytes (big ou little endian) é esperada, você pode precisa reordenar os bytes antes de enviar ou depois de receber.

Comentários

  • Muito direto e fácil de entender o princípio, obrigado, porém em " reconstruído " imprime apenas 5678?
  • Você copiou o snippet de código da minha resposta? Porque se eu executar o código no meu nodemcu, obtenho a resposta certa.
  • Sim, copiei e colei o código, adicionei void setup (); e Serial.begin (9600); para fazer o código rodar em meu arduino nano
  • por padrão em um AVR de 8 bits, ao lado direito dos padrões de igual para int aritmética que é assinada de dezesseis bits. Então, eu lancei a matriz para um uint32_t no loop. Não tenho certeza se essa é a maneira mais eficiente, mas funciona! Obrigado por sua ajuda
  • sim certo. Eu não ' não pensei sobre o controlador Arduino, quando tentei no nodemcu.

Resposta

O tipo union é semelhante a um struct, exceto que cada um dos membros do elemento ocupa o mesma memória. Se você definir um struct para que tenha 2 membros – um tipo de 4 bytes e uma matriz de 4 elementos de um único tipo de byte, então você pode facilmente referir-se aos mesmos dados como um elemento inteiro de 4 bytes, ou byte-wise como você deseja.

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

Este é o tipo, então você deve declarar que a variável é de esse tipo:

packed_long mydata; 

Agora, você tem dois subelementos de mydata: l e b[].

Para salvar seu long valor, escreva para l parte:

mydata.l = myaccel.getY(); 

Para acessar cada um dos 4 bytes:

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

Na extremidade receptora, você pega cada um dos 4 bytes:

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

Contanto que receba os bytes na mesma ordem no qual você os enviou, agora você pode acessar seu long valor em mydata.l.

O tamanho real de diferentes tipos é depende do compilador e da arquitetura, portanto, você também pode definir seu valor como uma variável de tamanho definido para garantir que esteja sempre trabalhando com 32 bits: int32_t (inteiro de 32 bits com sinal ) ou uint32_t (inteiro de 32 bits sem sinal).

Resposta

Uma maneira de enviar um long é mascarar e enviar o byte LSB (padrão CAN) e, em seguida, deslocar o próximo na posição LSB, para 4 bytes:

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

Comentários

  • OK, então CAN padrão é LSB primeiro. Como você tem conhecimento do CAN, pelo que posso descobrir eles enviam um pacote de 8 bytes, apenas um ou dois desses são os dados? Portanto, para um total de 16 bytes de informação, seriam necessários 8 pacotes?
  • Você me pegou! Isso ' s sobre tudo o que sei sobre o barramento CAN, e isso veio da Wikipedia . Há muita documentação do barramento CAN online; aquele artigo ' a bibliografia do artigo é um bom começo.
  • 8 bytes é o tamanho da carga de dados de um can-frame padrão. então você precisa de dois quadros padrão para enviar 16 bytes de informação. o can-fd mais recente suporta carga útil de dados de 64 bytes por quadro.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *