View previous topic :: View next topic |
Author |
Message |
Requan
Joined: 11 May 2008 Posts: 74
|
float to hex with union |
Posted: Tue Oct 23, 2012 6:34 am |
|
|
Hi,
I made union to convert float = 25.9 to union:
Code: |
union My_VarT
{
float ft;
int8 b[4];
}Temp;
|
In hex I get: 83 4F 33 33.
I can't decode it on PC program (c++ in union)/(c# bitconvert class)
When I used ccs function: f_PICtoIEEE, I get proper hex value: 33 33 CF 41, and I decoded in c++ and c# with success.
Why union in CCS convert with wrong results?
Best Regards,
Martin |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Tue Oct 23, 2012 7:42 am |
|
|
The union is giving the correct results. It is giving you exactly what the bytes contain on the PIC. Internally, CCS uses the Microchip float format, _not_ IEEE (except when you move to the DSPIC's). This was a special format designed to be fractionally more efficient to work with given the instruction limitations of the PIC (it saves a couple of instructions on most operations). fPICtoIEEE, converts from this format to the IEEE format.
If you want to save a bit of 'PIC time', you can convert instead at the PC end.
Code: |
float toIEEE(char data[]) {
//This is a routine to turn a float from the CCS format to the IEE format
union {
float value;
char bytes[4];
unsigned int word[2];
unsigned long int lword;
} block;
int sign;
//First re-arrange the byte order
block.bytes[3]=data[0];
block.bytes[0]=data[3];
block.bytes[1]=data[2];
block.bytes[2]=data[1];
//Now I have to take the sign bit from the top of byte 3, and move it past
//the exponent.
sign=block.bytes[2] & 128;
block.word[1]=(block.word[1] & 0x7F) & ((block.word[1]>>1) & 0x7F80);
block.bytes[3]=(block.bytes[3] & 0x7F) | sign;
return block.value;
}
char * toCCS(float value) {
//This is a routine to convert from IEEE to CCS. The inverse of the above.
static union {
float value;
char bytes[4];
unsigned int word[2];
unsigned long int lword;
} block;
int sign;
block.value=value;
sign=block.bytes[3] & 128;
block.word[1]=(block.word[1] & 0x7F) & ((block.word[1]<<1) & 0xFF00);
block.bytes[2]=(block.bytes[2] & 0x7F) | sign;
block.bytes[3]=block.bytes[0];
block.bytes[0]=block.bytes[3];
block.bytes[1]=block.bytes[2];
block.bytes[2]=block.bytes[1];
return &block.bytes[0];
}
|
The first accepts a four byte array and returns an IEEE float at the PC end. The second does the opposite.
Best Wishes |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Tue Oct 23, 2012 7:43 am |
|
|
All numbers are just notation. The same value can be represented different ways. unsigned Int8 notation is somewhat special since it can be directly operated upon by the PIC instructions. Now CCS PIC has a floating point notation and the format of the notation is described in the CCS manual. There are other notations IEEE for example. A CCS union between a float and 4 int8 is an overlay of the floating point notation onto 4 bytes. Microsoft can have its own floating point notation. The major style can be the leading byte in the notation being most significant or least significant. Within a byte is the leading bit most significant or least significant. There is a choice of the normal form of the mantissa 0.1nn 1.nnn and even as to how the sign is notated. Since the normal form has a leading 1 it can be used to store the sign and save storage space. Just as arithmetic works using roman numeral notation floating point is just another notation for arithmetic. Its value is that it can adjust the exponent to avoid small and large values running out of or using to much storage space...just as we use exponential notation to avoid running out of ink or paper when writing down large or very small numbers. |
|
|
Requan
Joined: 11 May 2008 Posts: 74
|
|
Posted: Wed Oct 24, 2012 1:26 am |
|
|
Ttelmah
Sorry but i don't feel pointers. I tried use your function but i get zero values, please look at my code below and please tell my what i did wrong:
Code: |
ftTemp = 25.9;
char arrTemp[4];
int8 *pointer;
pointer = arrTemp;
pointer = toCCS(ftTemp);
|
Best Regards,
Martin |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Wed Oct 24, 2012 2:14 am |
|
|
Code: |
float ftTemp;
char * pointer;
ftTemp=25.9;
b_pointer=toCCS(ftTemp);
|
toCCS, returns a pointer to an array, containing four bytes in the format to send to a CCS system, converted from the local float number.
You don't need to create the array the function does this.
b_pointer[0], b_pointer[1], b_pointer[2] and b_pointer[3] are the four bytes after this.
If you send these over a serial/USB link, and write them into the bytes of a union at the PIC end, the FP number there will be 25.9.
only limitation is that this assumes you are not running unicode at the PC (If you are, a char is no longer a byte).
Best Wishes |
|
|
Requan
Joined: 11 May 2008 Posts: 74
|
|
Posted: Wed Oct 24, 2012 2:56 am |
|
|
Quote: |
You don't need to create the array the function does this.
b_pointer[0], b_pointer[1], b_pointer[2] and b_pointer[3] are the four bytes after this.
|
Sorry but i don't understand - b_pointer is undefined identifier - i can't compile it.
To check how toCCS works i copy values from block.bytes to my array and send it via rs232. I get: 83 33 33 83 instead of 33 33 CF 41. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Wed Oct 24, 2012 3:53 am |
|
|
OK. I left the b out of the char declaration.
Use your mind a little though....
Best Wishes |
|
|
Raulsoft
Joined: 28 Jan 2010 Posts: 6
|
|
Posted: Wed Oct 24, 2012 11:09 am |
|
|
Hi
I use to send a variable float in the PIC HEX 4 bytes in CCS:
Code: |
float vTensao;
vTensao=25.9;
fprintf(UART2,"%8LX",vTensao);
|
note:
if use CCS PCD: 25.9 = 41CF3333
if use CCS PCW: 25.9 = 834F3333
see:
http://www.al-williams.com/fconvert.zip |
|
|
Raulsoft
Joined: 28 Jan 2010 Posts: 6
|
|
|
Requan
Joined: 11 May 2008 Posts: 74
|
|
Posted: Fri Oct 26, 2012 12:57 am |
|
|
Ttelmah
Thanks, now i understand and now it's working.
Thanks all for good advice |
|
|
|