Complemento de 13 bits 2 en .Net MF

5

Estoy utilizando un acelerómetro de triple eje ADXL345 a través de una placa de microestructura FEZmini1.3 .Net en un proyecto con el que estoy ocupado.

El ADXL345 proporciona datos en el complemento 2 de 13 bits.

¿Cómo decodificar esto en decimal?

He implementado un BitConverter ( según lo proporcionado por Ravenheart (Toshko) ) en el proyecto, pero seguramente esto supone un total de 16 bits (o dos bytes) de datos, donde el bit más significativo siempre será el bit de signo?

En un número de 13 bits, el 16 ° bit siempre será 0, ¿no?

       ------------Byte 1------------   ------------Byte 2-----------
bit#:  15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
16 bit: 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1 = -32767
13 bit: 0   0   0   1   1   1   1   1   1   1   1   1   1   1   1   1 = -4095

pero si el número de 13 bits se está convirtiendo mediante un algoritmo que supone 16 bits completos, el número será igual a 8192.

¿Mi entendimiento es correcto? En caso afirmativo, ¿cómo hago para convertir un número de complemento de 13 bits 2 en decimal?

Editar (después de obtener ayuda de mis amigos a continuación): Así que gracias a las respuestas, ahora sé que mis suposiciones del cumplido de 2 estaban equivocadas, así que para mayor claridad cuando alguien lee este hilo, quería corregir mi declaración inicial:

       ------------Byte 1------------   ------------Byte 2-----------
bit#:  15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
16 bit: 1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1 = -1
13 bit: 0   0   0   1   1   1   1   1   1   1   1   1   1   1   1   1 = -1

En 2's Compliment, los números cuentan hasta la mitad del camino y luego comienzan a contar, así que:

00000000 = 0
00000001 = 2
00000010 = 3
00000011 = 4
.
.
.
01111110 = 126
01111111 = 127
10000000 = -128
10000001 = -127
10000010 = -126
.
.
.
11111100 = -4
11111101 = -3
11111110 = -2
11111111 = -1
    
pregunta Gineer

5 respuestas

5

Para decodificar el número a decimal, conviértalo en algo que su procesador entienda de forma nativa, luego use las capacidades de conversión de binario a decimal existentes para convertir a decimal. Para convertir a la representación de enteros nativos, todo lo que tienes que hacer es firmar extender:

II is native signed integer
II <-- 13 bit signed A/D value  (get the A/D result)
II <-- II & 1FFFh               (make really sure limited to 13 bits)
if II >= 1000h                   (negative value ?)
  then II <-- II - 2000h        (convert to native negative)
Tenga en cuenta que esto es independiente del ancho del entero con signo nativo, siempre que sea más de 13 bits. Esto significa que esta técnica funciona para enteros con signo de 16 y 32 bits.

Editar: detalles fijos de la señal que se extiende arriba. Lo escribí justo en el papel del garabato al lado de mi teclado, luego lo copié en el post incorrecto. También se agregó una nota acerca de que es independiente del tamaño del entero nativo.

    
respondido por el Olin Lathrop
3

El microprocesador 6809 (¡el más hermoso 8-amargo de todos!) tenía una instrucción SEX , abreviada para "Sign EXtend" que convirtió un número de complemento de 8 bits 2 a 16 bits (el 6809 podría combinar sus dos acumuladores de 8 bits en un acumulador de 16 bits. Si el bit más alto era 1 (negativo), entonces el byte de orden superior se convertiría en 0xFF , de lo contrario 0x00 . Así que una extensión de signo en realidad copia el bit de signo a todos los bits anteriores. Puede OR con 0xE000 si el bit 12 está establecido:

if (adxl & 0x1000) {
  adxl |= 0xE000 };

Para convertir a decimal (BCD) Atmel tiene esta interesante nota de aplicación , que tiene algoritmos para BCD a binario y viceversa:

  

Conversión de binario de 16 bits a BCD de 5 dígitos
  Conversión de binario de 8 bits a BCD de 2 dígitos
  BCD de 5 dígitos a conversión binaria de 16 bits
  BCD de 2 dígitos a conversión binaria de 8 bits
  Adición de BCD empacado de 2 dígitos
  Resta de BCD empaquetada de 2 dígitos

Los algoritmos son independientes del procesador, aunque Atmel proporciona código fuente para el AVR.

    
respondido por el stevenvh
1

¿Cambiar a la izquierda tres veces? Eso le daría un entero con signo de 16 bits que coincidiría con el rango de los otros números con los que está trabajando.

No tendrás la resolución de bajo orden de tus otros sensores, pero será mucho más fácil trabajar con los valores.

00011111 11111111
Shift Left
00111111 11111110
Shift Left
01111111 11111100
Shift Left
11111111 11111000

En C puedes usar

val = val << 3;

En ASM habrá comandos de cambio a la izquierda apropiados. Es posible que deba desplazar bytes individuales y usar el indicador de acarreo para pasar bits de bits bajos a altos.

    
respondido por el Majenko
1

Necesitas hacer la extensión de signo, como dijeron los demás.

Hay varios métodos, consulte Hacker's Delight en Capítulo 2 Conceptos básicos en la página 18.

Editar: Me gusta el segundo método, adaptado a su caso, se convierte en

(x ^ 0x1000) – 0x1000

asumiendo que los tres bits más significativos son siempre cero ( ^ es exclusivo o).

    
respondido por el starblue
1

Si tienes un valor complementario de 13 bits 2, léelo en una variable con signo de 16 bits, muévelo hacia la izquierda en 16-13 = 3 bits, luego modifícalo a la derecha en tres bits, listo.

int16_t value = readValue(); // readValue returns a 13-bit 2's complement number
value = (value << 3) >> 3;   // sign extend the value

la variable value ahora contiene el valor decimal real.

Editar A la luz del comentario de @ Olin, quiero ser claro en mi respuesta. Aquí en términos más elaborados es cómo 0001 1111 1111 1111 se convierte en 1111 1111 1111 1111 explícitamente (según el ejemplo del OP), si entiendo la pregunta correctamente. El siguiente es un código C representativo.

uint8_t byte1 = 0x1F; //0b00011111
uint8_t byte2 = 0xFF; //0b11111111
int16_t value = (((uint16_t) byte1) * 256) + (byte2); // value now contains 0b0001111111111111
value = (value << 3) >> 3;                            // value now contains 0b1111111111111111
    
respondido por el vicatcu

Lea otras preguntas en las etiquetas