CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Convert 4 hex bytes to float

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
The_Todd



Joined: 11 Feb 2007
Posts: 5
Location: Santa Clara University

View user's profile Send private message

Convert 4 hex bytes to float
PostPosted: Wed Jul 18, 2007 11:51 pm     Reply with quote

I have a compass that outputs via serial a binary string containing the IEEE 754 standard binary representation of a float.

An example is:
43 81 81 9C
representing 259.01257 degrees

My issue is I cannot transform those four bytes into a float variable.

Things I've tried:
put the bytes into an array, and then make a pointer to a float variable, and try to set float bits using memset() - no effect

use bit_set() to try and set each bit in a float - doesn't affect it

Heres some sample test code maybe you could modify.
Code:

#include <18F4520.h>
#device ICD=TRUE
#FUSES HS,NOWDT,DEBUG,MCLR
#use delay(clock=20000000)
#use rs232(DEBUGGER)

int parts[4] = {0x43,0x81,0x81,0x9C}; //four bytes representing a float

void main()
{
int i=0;             //counter used in for loops
float heading = 0;   //the desired float to set
int *headingPtr;
int exponent = 0; 
int sign = 0;
headingPtr =& heading;

//try using a pointer
for(i=0;i<4;i++)
{
memset(headingPtr,parts[i],8);
headingPtr++;
}

printf("heading1:%f\r\n",heading);

//try to set bits individually - float should equal 4
bit_set(heading,30);
bit_set(heading,25);

printf("heading2:%f\r\n",heading);
}

I appreciate it greatly!
Todd
Ttelmah
Guest







PostPosted: Thu Jul 19, 2007 1:55 am     Reply with quote

The best thing to use is a union. If you have:
Code:

union joiner {
    int8 b[4];
    float fp;
    word w;
} combine;


Then you can write bytes into combine.b[0] to combine.b[3], and access the created float with combine.fp
Unfortunately (there has to be a downside...), CCS, doesn't use IEEE format floats. Fortunately, there is a library called 'ieeefloat.c', with the compiler to do the conversion (or I have published routines here in the past, before this came along, to do this). This library expects an int32 (hence my inclusion of the 'w' int32 int the above, so write the bytes into the four b values, and then call 'f_IEEEtoPIC' from this library, which does the bit re-shuffling needed to convert the type, and returns a PIC float.

Best Wishes
ljbeng



Joined: 10 Feb 2004
Posts: 205

View user's profile Send private message

PostPosted: Thu Jul 19, 2007 10:31 am     Reply with quote

I have what you need but I can't get the code to display correctly...

This is weird but I had to take out less-than characters.... Where you see

temp .. 1

replace with

temp (less than)(less than) 1 (shift left 1 bit)


Code:

float f_IEEEtoPIC(int32 f)
{
   float ret;
   int16 temp;
   memcpy(&temp, ((int8*)&f)+2, 2);
   temp = ((temp .. 1) & 0xFF00) + (temp & 0xFF);
   if(bit_test(f, 31))      // Test the sign bit
      temp |= 0x0080;
   else
      temp &= 0xFF7F;
   memcpy(((int8*)&ret)+3, ((int8*)&f)     , 1);
   memcpy(((int8*)&ret)+2, ((int8*)&f)+1   , 1);
   memcpy(((int8*)&ret)+1, ((int8*)&temp)  , 1);
   memcpy(((int8*)&ret)  , ((int8*)&temp)+1, 1);
   return ret;
}
int32 f_PICtoIEEE(float f)
{
   int16 c[2];
   memcpy((int8*)c  , ((int8*)&f)+3, 1);
   memcpy((int8*)c+1, ((int8*)&f)+2, 1);
   memcpy((int8*)c+2, ((int8*)&f)+1, 1);
   memcpy((int8*)c+3, ((int8*)&f)  , 1);
   c[1] = ((c[1] >> 1) & 0x7F80) + (c[1] & 0x7F) + ((c[1] & 0x80) << 8);
   return ((int32)c[1] << 16) | c[0];
}

main(){
   i32val = make32(0x43,0x81,0x81,0x9C);
   compass = f_IEEEtoPIC(i32val);
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Jul 19, 2007 11:47 am     Reply with quote

Quote:
I have what you need but I can't get the code to display correctly...

This is weird but I had to take out less-than characters...
This is caused by the text being interpreted as HTML code. Solution: on posting select the 'Disable HTML in this post' checkbox, or even better, select this option as default in your profile.
Ken Johnson



Joined: 23 Mar 2006
Posts: 197
Location: Lewisburg, WV

View user's profile Send private message

PostPosted: Thu Jul 19, 2007 5:51 pm     Reply with quote

look at ieeefloat.c in the drivers folder

Ken
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Fri Jul 20, 2007 1:56 am     Reply with quote

In floating pt the mantissa is normalized ( the exponent is adjusted to guarantee a 1 in the msb position of the mantissa). This is like writing the value in binary notation as 0.1nnnnnnnn to 23 bits raised to some power of two encoded in the exponent byte with an offset of 127 to allow for both positive and negative exponents. A special case for the exact value zero is allowed for.
The sign of the non zero values are stored as bit of the mantissa.Now with 4 bytes of storage there are choices as to what is done ... like does the exponent go in the first byte or in the last byte so we need standards to identify the coding scheme. Another wrinkle is since the normalized mantissa always has its most significant bit as a 1 use can be made of it. It can be replaced by the sign of the mantissa effectively gaining 24 bit precision at the expense of processing cycles since the sign would have to be extracted prior to doing any arithmetic with it. CCS uses 23 bit and uses an unadjusted normalized mantissa. The conversion routine ieeefloat.c in the drivers folder takes the work out of this for us.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group