Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manually cast signed char

Tags:

c

dynamic-c

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?

like image 431
Sean Taylor Avatar asked Sep 25 '11 14:09

Sean Taylor


People also ask

Can you cast unsigned char to char?

However, from i=128:255 the chars and the unsigned chars cannot be casted, or you would have different outputs, because unsigned char saves the values from [0:256] and char saves the values in the interval [-128:127]).

Can a char be signed?

@eSKay: yes, char is the only type that can be signed or unsigned. int is equivalent to signed int for example.

Is char automatically signed?

char is always unsigned. The three types char, signed char, and unsigned char are collectively called the character types.

Are char and signed char the same?

A char is a distinct type from signed char and unsigned char , and the three types are not compatible. For the purposes of distinguishing overloaded functions, a C++ char is a distinct type from signed char and unsigned char .


2 Answers

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;
}
like image 94
Raymond Chen Avatar answered Sep 24 '22 08:09

Raymond Chen


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.

like image 42
Chris Eberle Avatar answered Sep 22 '22 08:09

Chris Eberle