手动转换签名字符

发布于 12-06 09:46 字数 410 浏览 4 评论 0原文

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

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

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

当我收到此数据时,我将其放入 char 变量中,

这对于正值来说效果很好,但是当传感器开始发送负值时,读数会跳至 255,然后返回到 0。我认为这是因为最后一位用于确定负/正,并且扭曲了实际值。

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

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

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

I'm working with some embedded hardware, a Rabbit SBC, which uses Dynamic C 9.

I'm using the microcontroller to read information from a digital compass sensor using one of its serial ports.

The sensor sends values to the microcontroller using a single signed byte. (-85 to 85)

When I receive this data, I am putting it into a char variable

This works fine for positive values, but when the sensor starts to send negative values, the reading jumps to 255, then works its way back down to 0. I presume this is because the last bit is being used to determine the negative/positive, and is skewing the real values.

My inital thought was to change my data type to a signed char.

However, the problem I have is that the version of Dynamic C on the Microcontroller I am using does not natively support signed char values, only unsigned.

I am wondering if there is a way to manually cast the data I receive into a signed value?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

烧了回忆取暖2024-12-13 09:46:16

您只需拿出参考书并阅读控制器如何表示负数。剩下的就是打字了。

例如,二进制补码通过取模 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;
}

Sign-magnitude 通过设置高位来表示负数,因此只需清除该位并取反即可:

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

You just need to pull out your reference book and read how negative numbers are represented by your controller. The rest is just typing.

For example, two's complement is represented by taking the value mod 256, so you just need to adjust by the modulus.

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

One's complement is much simpler: You just flip the bits.

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

Sign-magnitude represents negative numbers by setting the high bit, so you just need to clear the bit and negate:

int signed_from_unsignedchar(unsigned char c)
{
    int result = c;
    if (result >= 128) result = -(result & 0x7F);
    return result;
}
如果没有2024-12-13 09:46:16

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

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

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

I think this is what you're after (assumes a 32-bit int and an 8-bit char):

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

of course I'm assuming here that your platform does support signed integers, which may not be the case.

陌上芳菲2024-12-13 09:46:16

有符号和无符号值都只是一堆位,您的解释使它们成为有符号或无符号的。例如,如果您的硬件生成 2 的补码,如果您读取 0xff,您可以将其解释为 -1 或 255,但它们实际上是相同的数字。

现在,如果您只有 unsigned char 可供使用,则必须用它来模拟负值的行为。

例如:

c < 0

更改为

c > 127

Luckyly,加法不需要更改。减法也是一样的(检查一下我不是100%确定)。

例如,对于乘法,您需要自己检查。首先,在 2 的补码中,以下是如何获得数字的正值:

pos_c = ~neg_c+1

从数学上讲是 256-neg_c ,同余模 256 就是 -neg_c code>

现在假设您想要将两个无符号数字相乘,但您希望将它们解释为有符号数字。

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;

你明白了!

Signed and unsigned values are all just a bunch of bits, it is YOUR interpretation that makes them signed or unsigned. For example, if your hardware produces 2's complement, if you read 0xff, you can either interpret it as -1 or 255 but they are really the same number.

Now if you have only unsigned char at your disposal, you have to emulate the behavior of negative values with it.

For example:

c < 0

changes to

c > 127

Luckily, addition doesn't need change. Also subtraction is the same (check this I'm not 100% sure).

For multiplication for example, you need to check it yourself. First, in 2's complement, here's how you get the positive value of the number:

pos_c = ~neg_c+1

which is mathematically speaking 256-neg_c which congruent modulo 256 is simply -neg_c

Now let's say you want to multiply two numbers that are unsigned, but you want to interpret them as signed.

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;

You get the idea!

昔梦2024-12-13 09:46:16

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

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

如果它是补码,请尝试以下操作:

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

这也会得到 0 到 170 之间的值。

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

If your platform supports signed ints, check out some of the other answers.

If not, and the value is definitely between -85 and +85, and it is two's complement, add 85 to the input value and work out your program logic to interpret values between 0 and 170 so you don't have to mess with signed integers anymore.

If it's one's complement, try this:

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

That will leave you with a value between 0 and 170 as well.

EDIT: Yes, there is also sign-magnitude. Then use the same code here but change the second line to x = 85 - (x & 0x7f).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文