¿Cómo convertir a un largo sin firmar desde una matriz de 4 caracteres?

1

Estoy programando un chip AVR (atmega1284p) con código c, estoy usando SPI para leer en 4 bytes de un chip en mi circuito. Me gustaría tomar esos 4 bytes y devolverlos como un largo sin firmar.

Puedo imprimir los bytes en el puerto serie y he recibido valores lógicos, que puedo calcular a mano para obtener el valor correcto. Luego trato de hacer esto con la programación y obtengo resultados muy peculiares. Aquí está el fragmento de código.

Nota: returnBytes es una matriz de 4 caracteres con los valores de caracteres correctos. Además, estoy usando una máscara de bits para asegurarme de que el cambio no tenga nada raro, simplemente en el caso (funciona de la misma manera con y sin máscara de bits).

unsigned long returnLong = (returnBytes[3]&0xFF)<<24;
returnLong |= (returnBytes[2]&0xFF)<<16;
returnLong |= (returnBytes[1]&0xFF)<<8;
returnLong |= (returnBytes[0]&0xFF);

return returnLong;

Lo que obtengo de esto es peculiar, ya que debería contar de 4.2bil a 0. Comienza alrededor de 4.2 bil, generalmente cuenta atrás y luego cae a 30.000 después de un par de conteos, luego salta de nuevo a 4.2bil después de un par de cuentas. (Sí, el contador regresará una vez que llegue a 0).

Estoy seguro de que los bytes son correctos y mi método de imprimir el largo sin firmar es correcto.

Aquí está la salida de este código (la primera línea es los bytes 3 2 1 0, la segunda línea es el valor del largo sin signo)

255 254 230 157
Counter Value: 4294960797
255 253 206 25
Counter Value: 4294954521
255 252 182 90
Counter Value: 4294948442
255 251 158 153
Counter Value: 4294942361
255 250 134 159
Counter Value: 4294936223
255 249 110 139
Counter Value: 28299
255 248 87 207
Counter Value: 22479
255 247 65 170
Counter Value: 16810

Esperemos que esta información sea suficiente.

    
pregunta Jake

1 respuesta

6

Hay dos respuestas posibles a esto, ya que un procesador puede ser bigendian , lo que significa que el byte con la dirección más baja es el más significativo o littlendian lo que significa que este byte es el menos significativo.

Asumiré que los bytes se almacenan en una matriz

unsigned char a[4];

y queremos el resultado en

unsigned long retval;

Si el sistema es bigendiano

retval  = (unsigned long) a[0] << 24 | (unsigned long) a[1] << 16;
retval |= (unsigned long) a[2] << 8 | a[3]; 

Si el sistema es littlendian

retval  = (unsigned long) a[3] << 24 | (unsigned long) a[2] << 16;
retval |= (unsigned long) a[1] << 8 | a[0];

Tenga en cuenta que los lanzamientos son necesarios porque de lo contrario pierde bits. Por ejemplo

retval = a[0] << 8;

Siempre debe ser cero, suponiendo que un char sin firma es de 8 bits porque

a[0] << 8

Desplazará los 8 bits de la variable de 8 bits y se perderán porque el compilador está haciendo aritmética de 8 bits. La respuesta resultante 0 se escribirá en la longitud de 32 bits.

Tener la conversión convierte el número en un [0] en un valor de 32 bits primero para que el desplazamiento no pierda estos bits.

    
respondido por el Warren Hill

Lea otras preguntas en las etiquetas