13,047,131 members (60,471 online)
Rate this:
See more: , +
Hi Everyone,

I'm trying to interpret some data from an embedded sensor device into a C++ program. The device uses a numerical format called 1.15 fractional format. This means it transmits 2 hex bytes into a value rangle of ~1 < n < -1.

A description of the format is given in this document (http://phobos.iet.unipi.it/~pieri/EdT2/2181_Manual/Appendix_C.pdf[^]).

I can understand how the format works (for example, negative values have a positive 15th bit) but I'm struggling to implement a convertor in C++ that can identify when the incoming data is negative.

So far I have this function, but it outputs incorrect data for negative numbers

```int Convert(BYTE msg0, BYTE msg1, float Target){

// Combine the 2 bytes
unsigned int F = msg0*256 + msg1;

// display the combined hex bytes and the decimal equivilant
// These values are correct
printf("\n\n Combined F = 0x%x \t F = %i",F,F);

double Ff = (double)F/(32767); // ((2^15)-1) = 32767 = 0x7FFF

printf("\n Ff = %f",Ff);

printf("\n Target = %f",Target);

return 0;
}```

The Target values are taken from the sensor documentation. As you can see my Positive outputs are pretty close (but not perfect) yet the negative values are way off.

Target______Hex_______Output
0.9999_____0x7FFF____1.000000
0.5_________0x4000____0.500015
-0.5________0xC000____1.500046
-1.0________0x8000____1.000031

Any suggestions greatfully recieved, I'm a little out of my depth here!
Posted 22-Oct-12 1:48am

Rate this:

## Solution 1

A couple of changes I would suggest are,
The largest positive number is 0x7fff / 0x8000. So instead of dividing by 32767, we need to divide by 32768.
Also, change the 'unsigned int F' declaration to 'short'. What this will do is give you the 2's complement negative number which you're looking for. Otherwise you can take the 2's complement yourself and get the correct magnitude for negative numbers (numbers starting with the 0x80 byte).

I hope this helps

Fantastic, those small changes solved it perfectly. I'd actually tried both those changes individually but not together! Many Thanks.
Rate this:

## Solution 2

According to the documentation signed numbers are represented in the two's complement format. To convert them you may use this:
```// Get the absolute number masking out the sign bit
int n = ((msg0 & 0x7F) << 8) + msg1;
// Get negative number:
//  0x8000 0x0000  -32768
//  ...
//  0xFFFF 0x7FFF  -1
if (msg0 & 0x80)
n -= 32768; // 0x8000
// Convert to double according to number of fractional bits
double f = (double)n / ((double)(1 << nFrac)); ```

This solution also works excellently. Thank you.

Top Experts
Last 24hrsThis month
 Graeme_Grant 142 Kornfeld Eliyahu Peter 110 Richard MacCutchan 104 Satya Prakash Swain 79 OriginalGriff 65
 OriginalGriff 4,868 RickZeeland 1,864 ppolymorphe 1,748 F-ES Sitecore 1,553 Dave Kreskowiak 1,379