7

我正在使用一些嵌入式硬件,即使用 Dynamic C 9 的 Rabbit SBC。

我正在使用微控制器使用其串行端口之一从数字罗盘传感器读取信息。

传感器使用单个有符号字节将值发送到微控制器。(-85 到 85)

当我收到这些数据时,我将它放入一个char变量中

这适用于正值,但是当传感器开始发送负值时,读数会跳到 255,然后又回到 0。我认为这是因为最后一位用于确定负/正,并且正在扭曲真实价值。

我最初的想法是将我的数据类型更改为signed char.

但是,我遇到的问题是我使用的微控制器上的 Dynamic C 版本本身不支持有符号字符值,只支持无符号值。

我想知道是否有办法将我收到的数据手动转换为有符号值?

4

4 回答 4

11

你只需要拿出你的参考书,看看你的控制器是如何表示负数的。剩下的就是打字了。

例如,二进制补码用取值 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;
}
于 2011-09-25T14:23:27.243 回答
1

我认为这就是你所追求的(假设一个 32 位 int 和一个 8 位 char):

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

当然,我在这里假设您的平台确实支持有符号整数,但情况可能并非如此。

于 2011-09-25T14:22:48.153 回答
1

有符号和无符号值都只是一堆位,是您的解释使它们有符号或无符号。例如,如果您的硬件产生 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;

你明白了!

于 2011-09-25T14:26:26.510 回答
0

如果您的平台支持signed ints,请查看其他一些答案。

如果不是,并且该值肯定在 -85 和 +85 之间,并且它是二进制补码,则将 85 添加到输入值并制定程序逻辑来解释 0 和 170 之间的值,这样您就不必弄乱有符号整数了。

如果它是一个人的补码,试试这个:

if (x >= 128) {
    x = 85 - (x ^ 0xff);
} else {
    x = x + 85;
}

这也会给你留下一个介于 0 和 170 之间的值。

编辑:是的,还有符号大小。然后在此处使用相同的代码,但将第二行更改为x = 85 - (x & 0x7f).

于 2011-09-25T14:36:49.130 回答