Entonces, después de 2 días de intentar esto, no puedo entenderlo.
Entonces estoy usando el bus CAN para transferir datos del acelerómetro y datos de tiempo (la función micros () si menos de 71 minutos generará datos que pueden ser sin firmar), sin embargo, tengo que enviar los datos como bytes. logré cambiar un bit int de 16 bits a 2 bytes, pero tengo problemas para extrapolar ese método (lo agregaré más adelante) para usar long. Tengo problemas para entender el método de unión ya que soy nuevo en la creación de mis propias funciones, entonces, ¿cómo ¿Podrían lograr esto? Tan simple como sea posible, por favor 🙂
Comentarios
- reste el byte máximo 3 que puede ser del total, y de que restar el byte máximo 2 puede ser para obtener el byte 3. El byte 4 es solo el byte máximo 4 menos el número menos el byte máximo 3 +1.
Respuesta
Puede lograr lo que desea usando desplazamiento de bits y operadores de bits y .
A continuación, se muestra un ejemplo que le permite extraer los bytes individuales de su variable long
. Creo que debería ser sencillo extenderlo a variables de diferente longitud:
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); }
Dependiendo del orden de bytes (endian grande o pequeño) que se espera, puede Necesito reordenar los bytes antes de enviar o después de recibir.
Comentarios
- Muy sencillo y fácil de entender el principio así que gracias, sin embargo bajo " reconstruido " solo imprime 5678?
- ¿Copiaste el fragmento de código de mi respuesta? Porque si ejecuto el código en mi nodemcu obtengo la respuesta correcta.
- Sí, copié y pegué el código, agregué void setup (); y Serial.begin (9600); para que el código se ejecute en mi arduino nano
- de forma predeterminada en un AVR de 8 bits, en el lado derecho de los valores predeterminados iguales a la aritmética int que está con signo de dieciséis bits. Entonces lanzo la matriz a un uint32_t en el ciclo. No estoy seguro de si esa es la forma más eficiente, ¡pero funciona! Gracias por su ayuda
- sí, claro. No ' no pensé en el controlador arduino, cuando probé el nodemcu.
Respuesta
El tipo union
es similar a un struct
excepto que cada uno de los miembros del elemento ocupa el mismo recuerdo. Si define un struct
de modo que tenga 2 miembros, un tipo de 4 bytes y una matriz de 4 elementos de un solo tipo de byte, entonces puede hacer referencia fácilmente a los mismos datos como un elemento completo de 4 bytes, o en bytes como desee.
union packed_long { long l; byte b[4]; };
Este es el tipo, por lo que debe declarar que la variable es de ese tipo:
packed_long mydata;
Ahora, tiene dos subelementos de mydata
: l
y b[]
.
Para guardar su long
, escriba en el l
parte:
mydata.l = myaccel.getY();
Para acceder a cada uno de los 4 bytes:
byte1 = mydata.b[0]; byte2 = mydata.b[1]; byte3 = mydata.b[2]; byte4 = mydata.b[3];
En el extremo de recepción, toma cada uno de los 4 bytes:
mydata.b[0] = canbus.read(); mydata.b[1] = canbus.read(); mydata.b[2] = canbus.read(); mydata.b[4] = canbus.read();
Siempre que reciba los bytes en el mismo orden en el que los envió, ahora puede acceder a su long
valor en mydata.l
.
El tamaño real de diferentes tipos es depende del compilador y la arquitectura, por lo que también puede definir su valor como una variable de tamaño definido para asegurarse de que siempre está trabajando con 32 bits: int32_t
(entero de 32 bits con signo ) o uint32_t
(entero de 32 bits sin signo).
Responder
Una forma de enviar un largo es enmascarar y enviar el byte LSB (estándar CAN), luego cambiar el el siguiente en la posición LSB, por 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 } //
Comentarios
- OK, entonces CAN estándar es LSB primero. Como usted tiene conocimiento de CAN, por lo que puedo encontrar, envían un paquete de 8 bytes, ¿son solo uno o dos de esos datos? Entonces, para un total de 16 bytes de información, ¿se necesitarían 8 paquetes?
- ¡Me atrapó! Eso ' es sobre todo lo que sé sobre el bus CAN, y eso fue de Wikipedia . Hay mucha documentación de bus CAN en línea; la bibliografía del artículo ' es un buen comienzo.
- 8 bytes es el tamaño de la carga útil de datos de un can-frame estándar. por lo que necesita dos marcos estándar para enviar 16 bytes de información. el can-fd más nuevo admite una carga útil de datos de 64 bytes por cuadro.