Получить целое число со знаком из 16 16-битных байтов со знаком? - PullRequest
1 голос
/ 16 марта 2012

Итак, этот датчик у меня возвращает значение со знаком в диапазоне от -500-500, возвращая два (старший и низкий) байты со знаком. Как я могу использовать их, чтобы выяснить, что является фактическим значением? Я знаю, что мне нужно сделать дополнение 2, но я не уверен, как. Это то, что у меня сейчас -

real_velocity = temp.values[0];
    if(temp.values[1] != -1)
        real_velocity += temp.values[1];

    //if high byte > 1, negative number - take 2's compliment
    if(temp.values[1] > 1) {
        real_velocity = ~real_velocity;
        real_velocity += 1;
    }

Но он просто возвращает отрицательное значение того, что было бы положительным. Так, например, -200 возвращает байты 255 (высокий) и 56 (низкий). Добавлены эти 311. Но когда я запускаю приведенный выше код, он говорит -311. Спасибо за любую помощь.

Ответы [ 5 ]

4 голосов
/ 16 марта 2012
 -200 in hex is 0xFF38, 

вы получаете два байта 0xFF и 0x38, преобразовав их обратно в десятичную, вы можете узнать их

0xFF = 255,
0x38 = 56

ваш датчик не возвращает 2 байта со знаком, а просто старший и младший байты 16-битного числа со знаком.

так что ваш результат

value = (highbyte << 8) + lowbyte

значение 16-битной переменной со знаком.

2 голосов
/ 16 марта 2012

Судя по приведенному вами примеру, значение уже является дополнением к 2. Вам просто нужно сдвинуть старший байт влево на 8 бит и ИЛИ значения вместе.

real_velocity = (short) (temp.values[0] | (temp.values[1] << 8));
1 голос
/ 16 марта 2012

Вы можете сдвигать биты и маскировать значения.

int main()
{
    char data[2];
    data[0] = 0xFF; //high
    data[1] = 56; //low
    int value = 0;

    if (data[0] & 0x80) //sign
        value = 0xFFFF8000;

    value |= ((data[0] & 0x7F) << 8) | data[1];

    std::cout<<std::hex<<value<<std::endl;
    std::cout<<std::dec<<value<<std::endl;
    std::cin.get();
}

Вывод:

ffffff38

-200

0 голосов
/ 16 марта 2012

Для 8-битных байтов сначала просто преобразуйте в unsigned:

typedef unsigned char Byte;
unsigned const u = (Byte( temp.values[1] ) << 8) | Byte( temp.values[0] );

Тогда, если это больше, чем верхний диапазон для дополнения 16-битных двух, вычтите 2 16 :

int const i = int(u >= (1u << 15)? u - (1u << 16) : u);

Вы могли бы делать трюки на битовом уровне, но я не думаю, что в этом есть какой-то смысл.

Выше предполагается, что CHAR_BIT = 8, что unsigned больше 16 бит, и что машина и желаемый результат являются дополнением до двух.


#include <iostream>
using namespace std;

int main()
{
    typedef unsigned char Byte;
    struct { char values[2]; } const temp = { 56, 255 };

    unsigned const  u = (Byte( temp.values[1] ) << 8) | Byte( temp.values[0] );
    int const       i = int(u >= (1u << 15)? u - (1u << 16) : u);

    cout << i << endl;
}
0 голосов
/ 16 марта 2012
real_velocity = temp.values[0];
real_velocity = real_velocity << 8;
real_velocity |= temp.values[1];
// And, assuming 32-bit integers
real_velocity <<= 16;
real_velocity >>= 16;
...