Searching \ for '[PIC] float to byte - byte to float in C' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/languages.htm?key=c
Search entire site for: 'float to byte - byte to float in C'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] float to byte - byte to float in C'
2007\03\08@153154 by Phillip Coiner

picon face

Hi All

I need to store some float types in the EEPROM of a PIC in my C18 code.

(I searched on the PICList web site but nothing is leaping out at me.)

To store the other C types I used an example routine from Microchip that
reads and writes bytes.

(BTW it works just fine but I remember changing the addressing part because
it used an unsigned char for the address portion that way I could address
more than 256 bytes)

When I needed to store integers and unsigned integers I was able to do that
with out much trouble.

I just masked off bytes one at a time and did a shift then stored them using
the trusty write a byte routine.

I then read the bytes and using shift operations I was able to reconstruct
my integers and of course unsigned integers.

Strings were a no brainer too just read with respect to the order written
one byte at a time.



Can someone tell me how to get the 4 bytes that comprise a float(MPLAB C18
format) and then how to turn those bytes back into a float using C?

The only way I can think to do it is to get the address of the float var and
then use inline ASM to manipulate the individual bytes.



(Seems like I've done this/some one showed me a clever C trick before but it
was a long time ago in a different environment.

I'll be danged if I can remember just how I did it exactly.  )



Thanks to the usual smart people in advance.

Phillip

Things should be as simple as possible but no simpler













Phillip
Things should be as simple as possible but no simpler



Phillip Coiner
CTO, GPS Source, Inc.


Your source for quality GNSS Networking Solutions and Design Services, Now!
{Original Message removed}

2007\03\08@154223 by Marcel Birthelmer

picon face
Phillip,

How about
unsigned char float_to_bytes[4] = *(unsigned char*) & my_float;

...

my_flot = *(float*)float_to_bytes;

As long as you keep the ordering of the bytes consistent, it should
work out alright.

- Marcel

2007\03\08@154903 by William Couture

face picon face
On 3/8/07, Phillip Coiner <spam_OUTpcoinerTakeThisOuTspamgpssource.com> wrote:
>
> Hi All
>
> I need to store some float types in the EEPROM of a PIC in my C18 code.

You can reference the individual bytes in a float by either using a union:
  union float_bytes
     {
     float value;
     unsigned char bytes[sizeof(float)];
     } myvar;

  myvar.value = 123.456;
  for (i = 0; i < sizeof(float); i++)
     {
     write_eeprom_byte(ee_base+i,myvar.bytes[i]);
     }

and read it by:

  for (i = 0; i < sizeof(float); i++)
     {
     myvar.bytes[i] = read_eeprom_byte(ee-base+i);
     }

Or you can use a pointer:

  unsigned char *p;
  float myval;
  myval = 123.456;
  p = (unsigned char *)&myval;
  for (i = 0; i < sizeof(float); i++, p++)
     write_eeprom_byte(ee_base+i,*p);

and read it by

  p = (unsigned char *)&myval;
  for (i = 0; i < sizeof(float); i++, p++)
     *p = read_eeprom_byte(ee_base+i);

Bill

--
Psst...  Hey, you... Buddy...  Want a kitten?  straycatblues.petfinder.org

2007\03\08@172326 by Phillip Coiner

picon face
Hi Marcel
Mucho thanks I'll try it as soon as my next meeting ends

I couldn't get it to compile in one fell swoop but this compiles.
unsigned char float_to_bytes[4] = {0}; // I'm told the complier zeros my
vars but old habits die hard
float_to_bytes[4]= *(unsigned char*) & my_float;


I have the same/similar issue with declaring vars after any code in my
functions.
For example if I try this

for(int i = 0; i < MAX_SATS; i++)
gives an error
So to get ride of the error I have to do this
(no code is allowed here only variable declarations)
int i = 0;

for(i = 0; i < MAX_SATS; i++)

if I try this

x char = 0;
x += 5;                 // if I do any thing before I finish my delcarations
then I get compile errors
int i = 0;
for(i = 0; i < MAX_SATS; i++)

I asked Microchip but their answer was that it should work.

When I read the bytes back from memory can I just do a straight cast back
the other direction like this?

my_float =  (float) *float_to_bytes;

Phillip
Things should be as simple as possible but no simpler



Phillip Coiner
CTO, GPS Source, Inc.


Your source for quality GNSS Networking Solutions and Design Services, Now!

-----Original Message-----
From: .....piclist-bouncesKILLspamspam@spam@mit.edu [piclist-bouncesspamKILLspammit.edu] On Behalf Of
Marcel Birthelmer
Sent: Thursday, March 08, 2007 1:42 PM
To: Microcontroller discussion list - Public.
Subject: Re: [PIC] float to byte - byte to float in C

Phillip,

How about
unsigned char float_to_bytes[4] = *(unsigned char*) & my_float;

...

my_flot = *(float*)float_to_bytes;

As long as you keep the ordering of the bytes consistent, it should
work out alright.

- Marcel

2007\03\08@173554 by Dario Greggio
face picon face
Hi Phillip, you're mixing some C++ (or maybe also C, but more recently :)
things with older ones,
specifically the for(int i=0 ...
and declarations after statements

--
Ciao, Dario

2007\03\08@180225 by Phillip Coiner

picon face

Hi Dario
That makes sense.
Thanks



Phillip
Things should be as simple as possible but no simpler



Phillip Coiner
CTO, GPS Source, Inc.


Your source for quality GNSS Networking Solutions and Design Services, Now!

-----Original Message-----
From: .....piclist-bouncesKILLspamspam.....mit.edu [EraseMEpiclist-bouncesspam_OUTspamTakeThisOuTmit.edu] On Behalf Of
Dario Greggio
Sent: Thursday, March 08, 2007 3:36 PM
To: Microcontroller discussion list - Public.
Subject: Re: [PIC] float to byte - byte to float in C

Hi Phillip, you're mixing some C++ (or maybe also C, but more recently :)
things with older ones,
specifically the for(int i=0 ...
and declarations after statements

--
Ciao, Dario

2007\03\09@125737 by Phillip Coiner

picon face
Hi Bill
I couldn't get Marcel's example to work....most likely because I wasn't
following the example correctly.
I was able to get the union example you suggested to work badda bing badda
boom.
I just wanted to say thanks again.


Phillip
Things should be as simple as possible but no simpler



Phillip Coiner
CTO, GPS Source, Inc.


Your source for quality GNSS Networking Solutions and Design Services, Now!
{Original Message removed}

2007\03\09@144105 by William Couture

face picon face
On 3/9/07, Phillip Coiner <pcoinerspamspam_OUTgpssource.com> wrote:
> Hi Bill
> I couldn't get Marcel's example to work....most likely because I wasn't
> following the example correctly.
> I was able to get the union example you suggested to work badda bing badda
> boom.
> I just wanted to say thanks again.

You're welcome.

Bill

--
Psst...  Hey, you... Buddy...  Want a kitten?  straycatblues.petfinder.org

2007\03\27@171611 by Barry Gershenfeld

face picon face
At 04:47 PM 3/8/07 -0500, William Couture wrote:

>You can reference the individual bytes in a float by either using a union:
>    union float_bytes
>       {
>       float value;
>       unsigned char bytes[sizeof(float)];
>       } myvar;
>
>    myvar.value = 123.456;
>    for (i = 0; i < sizeof(float); i++)
>       {
>       write_eeprom_byte(ee_base+i,myvar.bytes[i]);
>       }
>Bill

I have long wanted something that could do this, but alas, my K&R tells me:

" Any of these types may be assigned to u and then used in expressions, so
long as the usage is consistent: the type retrieved must be the type most
recently stored.  It is the programmer's responsibility to keep track of
which type is currently stored in a union; the results are
implementation-dependent if something is stored as one type and extracted
as another. "

I'd go as far as saying that C should have been provided with something
that did what you're trying above.  As an ex-assembly language programmer,
I resent being told how I can access my data :-)

Barry

2007\03\27@172828 by Marcel Birthelmer

picon face
> I have long wanted something that could do this, but alas, my K&R tells me:
>
> " Any of these types may be assigned to u and then used in expressions, so
> long as the usage is consistent: the type retrieved must be the type most
> recently stored.  It is the programmer's responsibility to keep track of
> which type is currently stored in a union; the results are
> implementation-dependent if something is stored as one type and extracted
> as another. "
>
> I'd go as far as saying that C should have been provided with something
> that did what you're trying above.  As an ex-assembly language programmer,
> I resent being told how I can access my data :-)

You don't really NEED unions, you can just go with (unsigned
char*)&myFloat to read the value as bytes:

unsigned char* bytes = (unsigned char*)&myFloat;
eeprom_write(bytes[0]);
eeprom_write(bytes[1]);
eeprom_write(bytes[2]);
eeprom_write(bytes[3]);

Something like that.

2007\03\27@173936 by Gerhard Fiedler

picon face
Marcel Birthelmer wrote:

> You don't really NEED unions, you can just go with (unsigned
> char*)&myFloat to read the value as bytes:
>
> unsigned char* bytes = (unsigned char*)&myFloat;
> eeprom_write(bytes[0]);

In the spirit of the recent discussion about type checking, there can be
said a word or two about minimizing the number of casts. A union like
suggested tells the reader of the code that this variable is meant to be
read byte-wise, so he better not change the internal representation without
looking carefully at /all/ code that accesses it. A cast somewhere deep in
the code doesn't provide the same type of code-inherent documentation.

OTOH, it can become tedious having to carry along the .value or similar
qualifier of the union through all the code (even though a good editor
helps a bit with this). It all depends, as usually... :)

Gerhard

2007\03\27@174032 by John Dammeyer

flavicon
face
Here's what I do:

void
Get_ObEEROM_Float(BYTE addr, float * pdata) {
 PBYTE pd = (PBYTE)pdata;
       *pd++ = Get_ObEEROM_Byte(addr++);
       *pd++ = Get_ObEEROM_Byte(addr++);
       *pd++ = Get_ObEEROM_Byte(addr++);
       *pd = Get_ObEEROM_Byte(addr);
}


I have a Delphi 5 windows application that converts the floating point
text into Microchip float format and then writes it over the serial port
as two 16 bit HEX values to the target which saves it into EEROM.

When the Delphi app is launched it reads a HEX dump of EEROM and pulls
the data into floats that are then displayed in the text boxes.  You
just have to make sure you keep track of BYTE ordering.

John Dammeyer

Automation Artisans Inc.
http://www.autoartisans.com
Ph. 1 250 544 4950


> {Original Message removed}

2007\03\27@174509 by John Temples

flavicon
face
On Tue, 27 Mar 2007, Barry Gershenfeld wrote:

> I have long wanted something that could do this, but alas, my K&R tells me:
>
> " Any of these types may be assigned to u and then used in expressions, so
> long as the usage is consistent: the type retrieved must be the type most
> recently stored.  It is the programmer's responsibility to keep track of
> which type is currently stored in a union; the results are
> implementation-dependent if something is stored as one type and extracted
> as another. "

That doesn't mean you can't do it; it just means that the behavior is
not defined by the standard and thus is not portable between different
compilers.

If you want to do it portably, convert the address of the float to an
unsigned char pointer, and use the pointer to walk through the bytes
of the float.

--
John W. Temples, III

2007\03\27@175600 by Gerhard Fiedler

picon face
Barry Gershenfeld wrote:

{Quote hidden}

This is kind of obvious, it seems to me. What's the problem? Isn't this the
exact purpose of storing two different variables in the same memory
location (independently of the language you're using for this): have the
memory being interpreted in different ways? Of course, if you store your
general string and read it as a double, you usually won't get a result that
makes a lot of sense. But doing with this feature something that makes
sense (like storing a float value byte by byte in an EEPROM) seems to make
sense to me :)

> I'd go as far as saying that C should have been provided with something
> that did what you're trying above.  

It is provided with something that does. Bill is not trying, he's showing
how this is done in C (two of the more common ways, anyway).

> As an ex-assembly language programmer, I resent being told how I can
> access my data :-)

Whenever you use a language (even assembly), you're being told by the tool
and by the target what you can do and what you can't do. The difference
doesn't seem to be that you're being told, but what you're being told :)

One major advantage of unions (vs type casts) is that they inherently
document how the data is supposed to be accessed. In this sense, there's a
huge difference between a float and a union float_bytes (as above): A float
implies that it doesn't matter if I implement it as a double (potentially
more precision, different internal format, but every calculation that is
done as a float should also work if done as a double). A union float_bytes
implies that the content is meant to be accessed byte-wise, so you should
not assume that you can replace it with a double and everything works as
before. It's a matter of reading what the code tells you and making
appropriate use of this.


BTW, K&R are really good for helping with the understanding of the essence
of C. But their accent, so to speak, is quite ancient and few current
compilers work according to K&R C. For the details, you're probably better
off with a C89 or C99 manual.

Gerhard

2007\03\27@180913 by Dave Tweed

face
flavicon
face
John Temples <@spam@piclist2KILLspamspamxargs.com> wrote:
> On Tue, 27 Mar 2007, Barry Gershenfeld wrote:
> > I have long wanted something that could do this, but alas, my K&R
> > tells me:
> >
> > "Any of these types may be assigned to u and then used in expressions,
> > so long as the usage is consistent: the type retrieved must be the type
> > most recently stored. It is the programmer's responsibility to keep
> > track of which type is currently stored in a union; the results are
> > implementation-dependent if something is stored as one type and
> > extracted as another. "
>
> That doesn't mean you can't do it; it just means that the behavior is
> not defined by the standard and thus is not portable between different
> compilers.
>
> If you want to do it portably, convert the address of the float to an
> unsigned char pointer, and use the pointer to walk through the bytes
> of the float.

Even that approach depends on the endianess of your hardware. To do
it truly portably, you have to assign the float value to an integer
variable that's at least as large (e.g., long or long long), and then
do the explicit shifting and masking to get at the individual bytes.
In the network world, this is known as "serializing" or "marshalling"
the data.

-- Dave Tweed

2007\03\27@182310 by Orin Eman

picon face
n 3/8/07, William Couture <KILLspambcoutureKILLspamspamgmail.com> wrote:
{Quote hidden}

I'd just use more general eeprom read/write functions which take a
count and pointer:

float fval;
write_eeprom(ee_base, (const unsigned byte *)&fval, sizeof(float));

read_eeprom(ee_base, (unsigned byte *)&fval, sizeof(float));

Orin.

2007\03\27@183256 by John Temples

flavicon
face
On Tue, 27 Mar 2007, Dave Tweed wrote:

> John Temples <spamBeGonepiclist2spamBeGonespamxargs.com> wrote:
>> If you want to do it portably, convert the address of the float to an
>> unsigned char pointer, and use the pointer to walk through the bytes
>> of the float.
>
> Even that approach depends on the endianess of your hardware.

It's portable in the sense that you're guaranteed to get all of the
bytes of the float without relying on implementation-defined or
undefined behavior.  Whether endianness is relevant to the application
is another matter.  They're not if you reading and writing a local
EEPROM.

> To do
> it truly portably, you have to assign the float value to an integer
> variable that's at least as large (e.g., long or long long),

How would you assign a float containing 3.141 to an integer?

--
John W. Temples, III

2007\03\27@194542 by Herbert Graf

flavicon
face
On Tue, 2007-03-27 at 15:32 -0700, John Temples wrote:
{Quote hidden}

Depends of course what precision you want. You could just do a i = f,
which would result in 3.

Otherwise decide on a "number of decimal places" and use fixed point
math, i.e. i = f*1000 -> 3141, nothing that there are 3 decimal places.

Personally, I've found there have been VERY few cases where I NEEDED
floating point numbers. I have used them on the PC side since they are
easy to use, but rarely have I NEEDED floats and couldn't have gotten by
with fixed point math.

TTYL

2007\03\27@210320 by peter green

flavicon
face
part 1 771 bytes content-type:text/plain; (unknown type 8bit not decoded)


> Even that approach depends on the endianess of your hardware. To do
> it truly portably, you have to assign the float value to an integer
> variable that's at least as large (e.g., long or long long), and then
> do the explicit shifting and masking to get at the individual bytes.
> In the network world, this is known as "serializing" or "marshalling"
> the data.
and even that is not nessacerally portable because the endian differences between your platforms may not be the same for integers as they are for floats.
--
No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.446 / Virus Database: 268.18.18/733 - Release Date: 25/03/2007 11:07




part 2 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2007\03\27@210320 by peter green

flavicon
face
part 1 1890 bytes content-type:text/plain; (unknown type 8bit not decoded)



{Quote hidden}

of course they are implementation dependant because the internal formats of data types vary between systems.

nearly all non trivial C programs rely on inplementation defined behaviour, the important thing is to remember how stuff behaves on all the common implementations (and #ifdef if nessacery)


--
No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.446 / Virus Database: 268.18.18/733 - Release Date: 25/03/2007 11:07




part 2 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2007\03\27@231346 by Orin Eman

picon face
On 3/27/07, peter green <EraseMEplugwashspamp10link.net> wrote:
>
> > Even that approach depends on the endianess of your hardware. To do
> > it truly portably, you have to assign the float value to an integer
> > variable that's at least as large (e.g., long or long long), and then
> > do the explicit shifting and masking to get at the individual bytes.
> > In the network world, this is known as "serializing" or "marshalling"
> > the data.
> and even that is not nessacerally portable because the endian differences between your platforms may not be the same for integers as they are for floats.

The whole point of marshalling is to avoid such problems...

Orin.

2007\03\27@233032 by peter green

flavicon
face
part 1 1598 bytes content-type:text/plain; (unknown type 8bit not decoded)



{Quote hidden}

yes properly done marshalling should avoid the problems but what was described in the post i replied to (assigning the float value to an integer that is just as large and then reading the individual bytes of that integer using shift/mask operators) is not properly done marshalling and will not solve the problems.


--
No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.446 / Virus Database: 268.18.18/733 - Release Date: 25/03/2007 11:07




part 2 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2007\03\28@035723 by Alan B. Pearce

face picon face
>Even that approach depends on the endianess of your hardware.

That is probably why K&R worded their book they way they did, so there was
no assumption that the bytes would be read in the correct order, whatever
the endianness of the processor.

More... (looser matching)
- Last day of these posts
- In 2007 , 2008 only
- Today
- New search...