Convert 4 bytes to floating point

General discussion on mikroC PRO for AVR.
Post Reply
Author
Message
rrsquez
Posts: 117
Joined: 23 Feb 2011 21:35

Convert 4 bytes to floating point

#1 Post by rrsquez » 03 Oct 2015 09:52

Hello, I am forced to save my floating point data as bytes to an external RAM. I have to break down these floating point numbers into bytes, then undo this process to recover the data. I found the floating point number format from Microchip AN575 (attached). A good example works a value all the way through.

The compiler already formats a floating point number to 4 bytes, but I need to break down this floating point number into those bytes so that I can save them. The AN575 will be useful to reconstruct the bytes when I want to read them back. How do I access the bytes of a floating point number?

My guess: Use the address of the floating point number as a base address, then use pointer arithmetic to access the individual bytes.

Before I do this work, is there a cleaner way to do this (other than letting the compiler do the work)? I have another post regarding external RAM, but I'd just like to focus on breaking down floating point numbers here.

Thank you, Richard V
00575.pdf
Last edited by rrsquez on 06 Oct 2015 05:29, edited 1 time in total.

aCkO
Posts: 1119
Joined: 14 Feb 2011 04:07
Location: Bar, Montenegro

Re: Convert 4 bytes to floating point

#2 Post by aCkO » 03 Oct 2015 11:16

Code: Select all

#include "built_in.h"

char bytes[4];
float f = 3.14;

bytes[0] = Lo(f);
bytes[1] = Hi(f);
bytes[2] = Higher(f);
bytes[3] = Highest(f);
Regards

rrsquez
Posts: 117
Joined: 23 Feb 2011 21:35

Re: Convert 4 bytes to floating point

#3 Post by rrsquez » 05 Oct 2015 21:38

Hello aCk0. Thank you for the quick reply. I tried using your code, and attached shows the results (and code). I don't understand why, but Hi, Lo, Higher and Highest all return values that are "larger" than 1 byte.

Let us follow the results for "0.50" as my floating point number. Here is what I get:

value is: 0.500000
eb value is: 0x83f // this is larger than 255 (larger than 1 byte)
f0 value is: 0x800 // this is larger than 255 (larger than 1 byte)
f1 value is: 0x800 // this is larger than 255 (larger than 1 byte)
f2 value is: 0x80a // this is larger than 255 (larger than 1 byte)

My data shows other results for other values (all powers of 2).

None of this makes any sense. I was following AN575 from Microchip, but I don't see this format being followed. Can you please help me make sense of this?

Thank you, Richard V

aCkO
Posts: 1119
Joined: 14 Feb 2011 04:07
Location: Bar, Montenegro

Re: Convert 4 bytes to floating point

#4 Post by aCkO » 05 Oct 2015 23:09

Your sprintf formatted string needs more than 20 characters. This is the source of memory corruption in the first place.

If you are using AVRs, keep in mind that Microchip uses modified IEEE754 format for floating-point numbers (see here: http://www.mikroe.com/forum/viewtopic.php?f=88&t=57662). Quick Converter tool of the IDE can be of great help.

You don't need to use additional array to extract bytes out of a floating point number. You can use built-in macros directly (Lo, Hi, Higher, Highest).

Regards

rrsquez
Posts: 117
Joined: 23 Feb 2011 21:35

Re: Convert 4 bytes to floating point

#5 Post by rrsquez » 06 Oct 2015 01:16

Hello aCk0. I tried your code, didn't you see the results I presented? I also tried increasing the memory buffer to 50, but that didn't help (same exact results).

Also, you didn't address the issue where I get 16 bits from a function that is only supposed to return 8. I have extra bits in my returned word, and I don't know how to get rid of them. I tried Masking (number & 0xff), but this actually zeroed out the whole number. The compiler is messing up; my proof is in my attached data and the code that created it. One thing to note, why does the 4th call to my function always produce this multiple byte output? In one set of data, I left out the upper byte, but it's still there (I just ignored it).

Would you please take a closer look at this? I've spent 8 hours today trying to make sense of your comments, the IEEE574 format, and AN575 (Microchip Tech. Ap Note). I also included my hand entered notes from conversions I observed using your code. It doesn't make sense, even if I move the bytes around. No exponent is in the ballpark (should be 0x7f offset).

Here are results I get using the example numbers in the Ap Note:

value is:50.265483
eb value is: 0xdbdb
f0 value is: 0xdb0f
f1 value is: 0xdb49
f2 value is: 0x4f42

Should be: 0x 84 49 0F DB
As you can see, I got the bytes all mixed up, and "0x84" is missing, but "0x42" is there instead (exactly half).

value is:0.156250
eb value is: 0x0
f0 value is: 0x0
f1 value is: 0x20
f2 value is: 0x4f3e

Should be: 0x 7C 20 00 00
As you can see, the "0x7c" byte is missing, but "0x3e" looks like it's taking it's place. Again, this is off by exactly by a factor of 2 again.

This is not following the format given in AN575, as the data is not the same. The proof is in this data.

Thank you, Richard V

aCkO
Posts: 1119
Joined: 14 Feb 2011 04:07
Location: Bar, Montenegro

Re: Convert 4 bytes to floating point

#6 Post by aCkO » 06 Oct 2015 02:32

rrsquez wrote:Hello aCk0. I tried your code, didn't you see the results I presented?
Yes, I did. Tried your code in software simulator and it works as expected as you can see from the screenshot below. You didn't mention which version of the compiler you are using. You might be experiencing some issues with sprintf library if you are using older version of the compiler.
debug.png
debug.png (68.68 KiB) Viewed 5525 times
rrsquez wrote:Here are results I get using the example numbers in the Ap Note:

value is:50.265483
eb value is: 0xdbdb
f0 value is: 0xdb0f
f1 value is: 0xdb49
f2 value is: 0x4f42

Should be: 0x 84 49 0F DB
No, it should not. It should be: 0x42 49 0F DB. Apparently, you are not reading my comments carefully. Microchip uses modified IEEE754 notation. Do not use AN575 if you are using AVRs. Atmel uses standard IEEE754 (https://en.wikipedia.org/wiki/Single-pr ... int_format). To convert from AN575 to standard IEEE754 just perform the circular right shift of the highest byte (84 -> 42):
quick converter.png
quick converter.png (9.21 KiB) Viewed 5525 times
Regards

rrsquez
Posts: 117
Joined: 23 Feb 2011 21:35

Re: Convert 4 bytes to floating point

#7 Post by rrsquez » 06 Oct 2015 04:37

Hello aCkO. Thank you for your patience with me, and that wealth of detailed response. I am using the latest AVR compiler (just bought it last month).

Sorry, I meant the "UART results", not the code itself. I keep getting extra bytes that I can't explain. This isn't simulated data, it's from a hardware port into HyperTerminal.

My apologies again, you wrote to use IEEE 754, but that's the document that AN575 refers too, so I thought you were pointing out something I already read in there. I saw the link you left, and see a big difference now. I also forgot to use the tool like you suggested. Thank you for the demonstration on that too. The data I have actually works, which is good (ignoring that upper garbage byte).

I think that I should have used "sprinti" instead of "sprintf". Do you think that matters regarding how many bytes I get back? As you can see from the data presented, I keep getting integer wide data passed through my "short int" variables.

Convert floating point into bytes
value is: 2.000000
eb value is: 0x840
f0 value is: 0x800
f1 value is: 0x800
f2 value is: 0x80a

Thank you, Richard V

aCkO
Posts: 1119
Joined: 14 Feb 2011 04:07
Location: Bar, Montenegro

Re: Convert 4 bytes to floating point

#8 Post by aCkO » 07 Oct 2015 13:59

rrsquez wrote:I think that I should have used "sprinti" instead of "sprintf". Do you think that matters regarding how many bytes I get back?
You don't get anything back. Sprintf is just a formatting function. Sprinti and sprintl are just crippled versions of sprintf that save you a lot of ROM size.

Anyway, your code is working fine. It will be much easier for everyone if you attach your whole project because I didn't get the results you described.

Here's the test code I used:

Code: Select all

#include "built_in.h"

void test_float2bytes(float value) {
  char txt[25];             // text message for UART
  unsigned short bytes[4];  // Why isn't this "bytes"
  float f;                  // Temporary floating point value

  bytes[0] = 0x0;           // This doesn't help. In fact, it makes it worse.
  bytes[1] = 0x0;
  bytes[2] = 0x0;
  bytes[3] = 0x0;

  f = value;    // make a copy
  bytes[0] = Lo(f);
  bytes[1] = Hi(f);
  bytes[2] = Higher(f);
  bytes[3] = Highest(f);

  sprintf(txt, "value is: %9.6f\r\n", value);
  UART1_Write_Text(txt);

  sprintf(txt, "eb value is: 0x%02X \r\n", bytes[3]);       // Diplay eb result
  UART1_Write_Text(txt);
    
  sprintf(txt, "f0 value is: 0x%02X \r\n", bytes[2]);       // Diplay f0 result
  UART1_Write_Text(txt);
  
  sprintf(txt, "f1 value is: 0x%02X \r\n", bytes[1]);       // Diplay f1 result
  UART1_Write_Text(txt);
  
  sprintf(txt, "f2 value is: 0x%02X \r\n", bytes[0]);       // Diplay f2 result
  UART1_Write_Text(txt);
}

void main() {
   UART1_Init(9600);
   
   while (1) {
      test_float2bytes(50.265483);
      Delay_ms(1000);
   }
}
Output:
vterm.png
vterm.png (6.18 KiB) Viewed 5501 times
Regards

arianofiran
Posts: 2
Joined: 26 Feb 2017 11:15

Re: Convert 4 bytes to floating point

#9 Post by arianofiran » 11 Oct 2020 07:00

do as this
union f2c{
float f;
unsigned char c[4];
}

store float to f2c.f and retrive bytes as f2c[0]..[3] and vis versa

Post Reply

Return to “mikroC PRO for AVR General”