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 CCS Technical Support

float to hex with union

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



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

float to hex with union
PostPosted: Tue Oct 23, 2012 6:34 am     Reply with quote

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: 19559

View user's profile Send private message

PostPosted: Tue Oct 23, 2012 7:42 am     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Tue Oct 23, 2012 7:43 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Oct 24, 2012 1:26 am     Reply with quote

Arrow 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: 19559

View user's profile Send private message

PostPosted: Wed Oct 24, 2012 2:14 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Oct 24, 2012 2:56 am     Reply with quote

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: 19559

View user's profile Send private message

PostPosted: Wed Oct 24, 2012 3:53 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Oct 24, 2012 11:09 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Oct 24, 2012 11:16 am     Reply with quote

see to:

http://www.piclist.com/images/floatconv10.zip
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Fri Oct 26, 2012 12:57 am     Reply with quote

Arrow Ttelmah
Thanks, now i understand and now it's working.

Thanks all for good advice
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