|
|
View previous topic :: View next topic |
Author |
Message |
The_Todd
Joined: 11 Feb 2007 Posts: 5 Location: Santa Clara University
|
Convert 4 hex bytes to float |
Posted: Wed Jul 18, 2007 11:51 pm |
|
|
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
|
|
Posted: Thu Jul 19, 2007 1:55 am |
|
|
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
|
|
Posted: Thu Jul 19, 2007 10:31 am |
|
|
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
|
|
Posted: Thu Jul 19, 2007 11:47 am |
|
|
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
|
|
Posted: Thu Jul 19, 2007 5:51 pm |
|
|
look at ieeefloat.c in the drivers folder
Ken |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Fri Jul 20, 2007 1:56 am |
|
|
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. |
|
|
|
|
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
|