Вручную разыграть подписанный символ - PullRequest
7 голосов
/ 25 сентября 2011

Я работаю с некоторым встроенным оборудованием, Rabbit SBC, которое использует Dynamic C 9.

Я использую микроконтроллер для считывания информации с цифрового датчика компаса, используя один из его последовательных портов.

Датчик отправляет значения в микроконтроллер, используя один байт со знаком. (От -85 до 85)

Когда я получаю эти данные, я помещаю их в char переменную

Это работает нормально для положительных значений, но когда датчик начинает отправлять отрицательные значения, показание переходит на 255, а затем возвращается обратно к 0. Я предполагаю, что это потому, что последний бит используется для определения отрицательного / положительный, и искажает реальные значения.

Моей первоначальной мыслью было изменить тип данных на signed char.

Однако проблема, с которой я столкнулся, заключается в том, что версия Dynamic C на используемом мной микроконтроллере изначально не поддерживает значения знаков со знаками, только без знака.

Мне интересно, есть ли способ вручную преобразовать полученные данные в значение со знаком?

Ответы [ 4 ]

11 голосов
/ 25 сентября 2011

Вам просто нужно вытащить справочник и прочитать, как отрицательный номер представлен вашим контроллером.Остальное просто печатать.

Например, два дополнения представлены принятием значения mod 256, поэтому вам просто нужно отрегулировать по модулю.

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result -= 256;
    return result;
}

Дополнение к одному намного проще: вы просто переворачиваете биты.

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result = -(int)(unsigned char)~c;
    return result;
}

Величина знака представляет отрицательные числа, устанавливая старший бит, поэтому вам просто нужно сбросить бит и отрицать:

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result = -(result & 0x7F);
    return result;
}
1 голос
/ 25 сентября 2011

Значения со знаком и без знака - это просто куча битов, это ВАША интерпретация, которая делает их знаковыми или неподписанными.Например, если ваше оборудование выдает 2 дополнения, если вы читаете 0xff, вы можете интерпретировать его как -1 или 255. Но на самом деле это одно и то же число.

Теперь, если в вашем распоряжении только unsigned charвы должны имитировать поведение отрицательных значений с ним.

Например:

c < 0

меняется на

c > 127

К счастью, дополнение не нуждается в изменении,Также вычитание такое же (отметьте это, я не уверен на 100%).

Для умножения, например, вам нужно проверить это самостоятельно.Во-первых, в дополнении к 2, вот как вы получаете положительное значение числа:

pos_c = ~ neg_c + 1

, что с математической точки зрения 256-neg_c, которое по модулю 256 просто -neg_c

Теперь предположим, что вы хотите умножить два числа без знака, но вы хотите интерпретировать их как подписанные.

unsigned char abs_a = a, abs_b = b;
char final_sign = 0; // 0 for positive, 1 for negative
if (a > 128)
{
    abs_a = ~a+1
    final_sign = 1-final_sign;
}
if (b > 128)
{
    abs_b = ~b+1
    final_sign = 1-final_sign;
}
result = abs_a*abs_b;
if (sign == 1)
    result = ~result+1;

Вы поняли!

1 голос
/ 25 сентября 2011

Я думаю, что это то, что вам нужно (предполагается, что 32-битное int и 8-битное char):

unsigned char c = 255;
int i = ((int)(((unsigned int)c) << 24)) >> 24;

конечно, я предполагаю, что ваша платформа поддерживает целые числа со знаком, что может быть и не так.

0 голосов
/ 25 сентября 2011

Если ваша платформа поддерживает signed int s, проверьте некоторые другие ответы.

Если нет, и значение определенно находится в диапазоне от -85 до +85, и это дополнение к двум, добавьте 85 квходное значение и разработайте логику вашей программы для интерпретации значений от 0 до 170, чтобы вам больше не приходилось связываться с целыми числами со знаком.

Если это дополнение, попробуйте это:1008 * Это также даст вам значение от 0 до 170.

РЕДАКТИРОВАТЬ: Да, есть также величина знака.Затем используйте тот же код, но измените вторую строку на x = 85 - (x & 0x7f).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...