Problemas con arrays

Buenos días a todos.
Tengo una serie de problemas con los arrays que para mi no tienen logica y no consigo entender que está fallando. Esto es parte de un código mucho mas amplio pero que he aislado para hacer pruebas. Basicamente necesito poder convertir números enteros de 2 y 4 bytes en arrays y viceversa en BigEndian.

void loop() {

  uint16_t i = 512;
  uint32_t i2 = 12786783;

  uint8_t buffer[sizeof(uint16_t)];

  uInt16ToArray(i, buffer);

  Serial.println("Array UInt16:");
  printArrayHex(buffer, sizeof(uint16_t));


  uint16_t newvalue = arrayToUInt16(buffer);
  Serial.print("El valor numerico es: "); Serial.println(newvalue);

  Serial.println("-----------------------");


  uint8_t buffer2[sizeof(uint32_t)];

  uInt32ToArray(i2, buffer2);

  Serial.println("Array UInt32:");
  printArrayHex(buffer2, sizeof(uint32_t));

  uint32_t newvalue2 = arrayToUInt32(buffer2);
  Serial.print("El valor numerico es: "); Serial.println(newvalue2);



  Serial.println("");Serial.println("----------");Serial.println("");


  delay(5000);

}

Esto parece simple, un numero de 2 bytes y otro de 4 que he escogido al azar.

Las funciones son las siguientes:

void uInt16ToArray(uint16_t value, uint8_t *array) {

    uint8_t len = sizeof(uint16_t);
    uint8_t data1[len];
    memcpy(data1, &value, len);

    array[0] = data1[1];
    array[1] = data1[0];

}


uint16_t arrayToUInt16(const uint8_t *d) {

  uint16_t data;

  data = 0;
  data += (uint16_t)d[0] << 8;
  data += (uint16_t)d[1];

  return data;

}


void uInt32ToArray(uint32_t value, uint8_t *array) {

    uint8_t len = sizeof(uint32_t);
    uint8_t data[len];
    memcpy(data, &value, len);

    array[0] = data[3];
    array[1] = data[2];
    array[2] = data[1];
    array[3] = data[0];

}

uint32_t arrayToUInt32(const uint8_t *d) {

  uint32_t data;

  data = 0;
  data += (uint32_t)d[0] << 24;
  data += (uint32_t)d[1] << 16;
  data += (uint32_t)d[2] << 8;
  data += (uint32_t)d[3];

  return data;

}

Resulta que la primera pasada pone esto:

Array UInt16:
02-00
El valor numerico es: 47288

Array UInt32:
08-B8-B8-B8
El valor numerico es: 3099113656

El array del primer valor es correcto, 02-00 equivale al 512. Pero luego la conversión es incorrecta. El valor del segundo numero es todo incorrecto.

En las siguientes pasadas ya lo hace todo mal:

Array UInt16:
08-B8
El valor numerico es: 47288

Array UInt32:
08-B8-B8-B8
El valor numerico es: 3099113656

Lo extraño es que si elimino la parte del código donde hago la conversión del segundo numero (de 4 bytes), hace todo el proceso correctamente con el numero 512.

Saludos!

No veo el fallo.

He cambiado el código un poco, para añadir la funcion printArrayHex que no has proporcionado y añadido algunos print para ver mejor un poco el resultado y no veo que falle. Tu codigo de funciones ni lo he tocado.

void setup() {
  Serial.begin(9600);
}

void uInt16ToArray(uint16_t value, uint8_t *array) {
    uint8_t len = sizeof(uint16_t);
    uint8_t data1[len];
    memcpy(data1, &value, len);
    array[0] = data1[1];
    array[1] = data1[0];
}


uint16_t arrayToUInt16(const uint8_t *d) {
  uint16_t data;
  data = 0;
  data += (uint16_t)d[0] << 8;
  data += (uint16_t)d[1];
  return data;
}


void uInt32ToArray(uint32_t value, uint8_t *array) {

    uint8_t len = sizeof(uint32_t);
    uint8_t data[len];
    memcpy(data, &value, len);

    array[0] = data[3];
    array[1] = data[2];
    array[2] = data[1];
    array[3] = data[0];

}

uint32_t arrayToUInt32(const uint8_t *d) {

  uint32_t data;

  data = 0;
  data += (uint32_t)d[0] << 24;
  data += (uint32_t)d[1] << 16;
  data += (uint32_t)d[2] << 8;
  data += (uint32_t)d[3];

  return data;

}
void printArrayHex(uint8_t *b, uint8_t l){
  for (int x=0; x<l; x++) {
    Serial.print(b[x], HEX);
    Serial.print('-');
  }
  Serial.println();
}
void loop() {
  uint16_t i  = 512;
  uint32_t i2 = 12786783;
  uint8_t buffer[sizeof(uint16_t)]; // uint8_t buffer[2];
  uInt16ToArray(i, buffer);

  Serial.println("Array UInt16:");
  Serial.print("Valor: "); Serial.print(i);
  Serial.print(" ("); Serial.print(i,HEX); Serial.println(")");
  printArrayHex(buffer, sizeof(uint16_t));
  uint16_t newvalue = arrayToUInt16(buffer);
  Serial.print("El valor numerico es: "); Serial.print(newvalue);
  Serial.print(" ("); Serial.print(newvalue, HEX); Serial.println(")");

  Serial.println("-----------------------");

  uint8_t  buffer2[sizeof(uint32_t)];
  uint32_t newvalue2;

  uInt32ToArray(i2, buffer2);

  Serial.println("Array UInt32:");
  Serial.print("Valor: "); Serial.print(i2);
  Serial.print(" ("); Serial.print(i2,HEX); Serial.println(")");
  printArrayHex(buffer2, sizeof(uint32_t));
  newvalue2 = arrayToUInt32(buffer2);
  Serial.print("El valor numerico es: "); Serial.println(newvalue2);
  Serial.print(" ("); Serial.print(newvalue2, HEX); Serial.println(")");
  
  delay(5000);
}

Gracias por la respuesta,
el codigo de impresión del array es el siguiente:

void printHex(uint8_t num) {

  char hexCar[2];
  sprintf(hexCar, "%02X", num);
  Serial.print(hexCar);

}

void printArrayHex(uint8_t *b, uint8_t size) {

  for(int i=0; i < size; i++){

    printHex(b[i]);

    if (i<(size-1)) Serial.print("-");

  }

  Serial.println("");

}

No puse la función pensando que no tendria mayor importancia, fue un copy paste de algo que vi por internet (mal hecho por mi parte). Resulta que si cambio a como tu lo imprimes funciona bien, pero si uso mi función ya empieza ha hacerlo mal. No sé muy bien el motivo...

El problema está ahí, en la definición de hexCar[2], ese 2 debería de ser un 3. Las cadenas de C utilizan un último byte con el valor cero para indicar el final de la cadena. Es por eso que se necesita que el tamaño del array tenga un byte más de la longitud del texto que se pretende almacenar. Es un error muy común, que lleva a que el programa pueda hacer cosas muy raras e inexplicables. Debido a que muchas veces puede alterar el valor de una variable que se aloja en la memoria contigua a donde se aloja el array "conflictivo". En este caso, la función sprintf mete en el array tres elementos. Los dos dígitos que se eperan y el valor cero detrás de ellos. Aunque se declare el array de tan solo dos elementos, la función "escribe" más allá de los bytes reservados. Es lo malo que tiene las cadenas de C, que no verifican si se salen del área reservada para ellas. Lo bueno es que es más rápido al no "perder el tiempo" haciendo comprobaciones.

Si se cambia el 2 por un 3, debería de resolverse el problema y dar el resultado esperado.

void printHex(uint8_t num) {

  char hexCar[3]; // Para tener una cadena de 2 caracteres "útiles", se necesita un array de 3 bytes. El tercer byte valdrá cero, para indicar el final de la cadena.

Correcto, asunto solucionado. he cambiado el 2 por un 3 y ya funciona perfecto. Me estaba volviendo loco, es de estos errores que pierdes tiempo y luego resulta ser una tonteria.

Gracias por todo!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.