printf does not print float value correctly

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

printf does not print float value correctly

1,161 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jimmcwin on Tue Jun 26 10:08:02 MST 2012
I am trying to find out why printf is having problem printing floating data. Is this because of M4 FPU ?


Jim
Labels (1)
0 Kudos
2 Replies

834 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jimmcwin on Fri Jun 29 16:35:41 MST 2012
Thanks. I found the problem actually very simple: The current stack of any function or context within a printf call needed to be aligned by 8.

Jim
0 Kudos

834 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bavarian on Wed Jun 27 00:33:21 MST 2012
Hello Jim,

not that much information about your problem ;-)

One thing: the behavior of printf is not related to the existence of an FPU. It is related to the library you use (KEIL MicroLib, standard libs, NewLib from GCC etc).

At least in the NewLib (so if you use the free LPCXpresso tools) I remember a problem. Please look at the code snippet below for a workaround, plus an alternative. The alternative saves quite some memory, if you use %f then a lot of library stuff gets linked in, maybe just for one printf instruction.

Example:
========

#ifdef EXTMEMORY      // Functions of the newlib require more memory, so use them if we have external SRAM
  char latbuf[128];     // String buffer for latitude value of a GPS coordinate
  char longbuf[128];    // String buffer for longitude value of a GPS coordinate
#else                 // Substitute the newlib functions with a more simple implementation
  double f1, f2;
  unsigned short d1, d2, n1, n2;
#endif

#ifdef EXTMEMORY
  // Workaround for a limitation of sprintf in the newlib with %f:
  //   Convert the float into a string using  char *gcvt(double val, int precision, char *buf)
  //   Note: This requires some amount of memory
  gcvt(Nav_Data.Latitude, 6, latbuf);     // Nav_Data.Latitude is a floating-point value
  gcvt(Nav_Data.Longitude, 6, longbuf);   // Nav_Data.Longitude is a floating-point value
  sprintf(buf, "3D fix: %sN %sE\r\n", latbuf, longbuf);
  xDebugPutString( buf, strlen(buf) );
#else  // workaround for the memory consuming library version
  d1 = Nav_Data.Latitude;    // Get the integer part
  d2 = Nav_Data.Longitude;   // Get the integer part

  f1 = Nav_Data.Latitude - d1;     // Get the fractional part
  f2 = Nav_Data.Longitude - d2;    // Get the fractional part

  n1 = (u16)(f1 * 10000);    // Turn into integer with 5 digits
  n2 = (u16)(f2 * 10000);    // Turn into integer with 5 digits

  // Print as parts, note that you need 0-padding for fractional bit.
  // Since d1 is 678 and d2 is 123, you get "678.0123".
  sprintf (buf, "3D fix: %d.%04dN %d.%04dE\r\n", d1, n1, d2, n2);
  xDebugPutString( buf, strlen(buf) );
#endif


Best regards.
0 Kudos