Convertir complemento de 2 de 32 bits a número decimal

Tengo datos provenientes de un chip de medición de energía V9261F ( enlace a la hoja de datos ), que los envía a través de un UART a mi microcontrolador Arduino. Cuando leo el registro 0x0119, leo la potencia activa medida por el chip. Pero el problema es que esta retroalimentación está en complemento de 2 de 32 bits y no puedo decodificarla.

comunicación UART

A partir del 4.º byte del flujo se encuentran los bytes de datos en los que se almacenan las variables medidas (ver hoja de datos, págs. 56 - 57). Para leer el registro 0x0119, este debe estar en el byte de datos 10 - 11 - 12 y 13 (D1) respectivamente 0x55, 0xE7, 0x0E y para el byte de datos 13 0x00.

Entonces, la retroalimentación para la potencia activa de todos los bytes combinados que tengo es 0x000EE755 -> restar 1 (para 1 complemento) = 0x000EE754 -> invertirlo para convertirlo en un número decimal = 0xFFF118AB (4293990571 dec). Pero este gran número loco solo debería representar una potencia activa de 6,2 vatios.

¿Qué hago mal al convertir del complemento a 2 a decimal? ¿Cómo debería representar esto 6,2 vatios?

Respuestas (3)

Creo que tienes un malentendido de lo que significa "complemento a 2". Un número de complemento a 2 positivo es idéntico a un número binario positivo (el bit más significativo debe ser cero). Así que para 8 bits tenemos 0x00 (cero) a 0x7F (127). Los números menores que cero van de 0xFF (-1) a 0x80 (-128). Para hacer que un número negativo sea positivo para que pueda mostrarlo como un signo menos delante de un número positivo, puede calcular el complemento a 2 como se muestra arriba. Tenga en cuenta el caso especial de 0x80.

Entonces, con 0x000EE754, tiene un número positivo de decimal 976724. Hay un factor de escala entre eso y 6.2 de 6.3478E-6.

Probablemente lo que quieras hacer es convertir el número en un número de coma flotante y hacer los cálculos en coma flotante. Ya está en formato de entero con signo de 32 bits .

El complemento a dos es un formato para describir números negativos . Se aplica cuando el número es negativo. Tus cálculos no tienen ningún sentido. https://en.wikipedia.org/wiki/Two%27s_complemento

Según RTFM, el formato de datos del dispositivo es Little Endian de 32 bits en complemento a 2. Entonces, dado que su MCU es little endian (que es el caso con AVR), no necesita convertir nada. Simplemente almacene el resultado en un archivo int32_t.

El formato de datos para UART es LSB primero y la herramienta que hizo la imagen parece ser consciente. Entonces, si tiene algunos datos como 55e70e00, entonces esa es la lectura de datos real. Dado que es little endian, corresponde al hexadecimal 0x000ee755, decimal 976725. Este es el valor con el que debe terminar después de leer el registro rx de UART. Si este número tiene sentido, no tengo ni idea.

El complemento a 2 no importa ya que el número es positivo en este caso. Un número negativo tendría un 1 binario en el MSB.

OK, gracias por aclarar esto. Comprobaré si no se utiliza ningún factor de escala al realizar mediciones de carga múltiples. Bastante extraño que no se anote nada del factor de escala en las hojas de datos.
La afirmación "El complemento a dos es un formato para describir números negativos". no es exacto El formato de "complemento a dos" describe todos los números, no solo los negativos. Simplemente se vuelve más interesante para los números negativos.
Más bien, el complemento a dos es una convención de signos para representar números enteros .

La forma en que me gusta pensar en los números en complemento a dos es pensar en lo que sucede con los bits inferiores de un número binario al restar. Si los 4 bits inferiores de x son 0000 y los cuatro bits inferiores de y son 0001, entonces los cuatro bits inferiores de xy serán 1111 independientemente de los bits que estén encima de ellos. Esto se puede generalizar fácilmente para cualquier número particular de bits (restar un número cuyos bits inferiores expresan el valor 1 de un número cuyos bits inferiores expresan el valor 0 dará como resultado un número cuyos bits inferiores están todos establecidos). Dado que eso funcionará para cualquier cantidad de bits, se puede generalizar aún más para decir que restar uno de cero producirá un número con una cantidad infinita de bits establecidos.

En la práctica, almacenar un número infinito de bits no es práctico. Sin embargo, para cualquier N>=1, todos los números dentro del rango -(2^N) a (2^N)-1, sin embargo, todos los bits a la izquierda del enésimo bit (contando hacia la izquierda) tendrán el mismo valor que el bit N-ésimo en sí mismo y, por lo tanto, no es necesario almacenarlo. Por lo tanto, cuando se utilizan valores de complemento a dos de 8 bits, el valor -1 no es "realmente" 10000000, sino que es [número infinito de 1] 0000000, y el valor 127 no es 01111111, sino [número infinito de 0s]1111111. Ver las cosas de esta manera dejará en claro cómo deberían funcionar las conversiones entre diferentes tamaños de valores.

Por ejemplo, convertir el valor de 8 bits a 16 bits simplemente implicaría copiar parte de la cadena infinita de 1 o ceros, mientras que convertir un valor de 16 bits en el rango -128..127 a 8 bits implicaría eliminar algunos duplicados. pedacitos Si un número de 16 bits está fuera de ese rango, convertirlo a 8 bits produciría el valor que resultaría de copiar el bit retenido más significativo.

PD: aplicando la fórmula de suma de potencias 1+2+4+8... se obtiene -1. Eso puede parecer una tontería, pero encaja perfectamente con el funcionamiento de las matemáticas en complemento a dos. Para cualquier valor de N, si los N bits inferiores de un número están todos establecidos, sumar 1 producirá un número cuyos N bits inferiores están todos limpios. El único número para el que los N bits inferiores serán claros para todos los valores de N es cero, y el único número que dará 0 cuando se le suma 1 es, por supuesto, -1.