Using sprintf function for float numbers in AVR-GCC

Usually it is not recommended to use float numbers in while writing AVR programs,because AVR core doesn't have floating point arithmetics built in so floating point arithmetics is emulated by software. Sometimes you don't need to declare variables as float if operations are pretty simple like division or multiplying by 2, 4, 8... this can be replaced by byte shift operation (byte<<1)=byte*2. Of course it depends on level of programming and not always you can run away from floats. And you don't have to. If you code will fit to Program memory and execution speed isn't crucial then use floats or double number formats.

Lets see what happens when building simple program with float numbers:

#include <stdint.h>

#include <stdio.h>

#include <avr/io.h>

#include "global.h"

#include "rprintf.h"

#include "timer.h"

#include "lcd.h"

int main(void){

char mystr[16];

double myflt1, myflt2;

myflt1 = 3.14159;

myflt2 = myflt1*5.1324;

sprintf(mystr, "%.5f", myflt2);

lcdInit();

lcdPrintData(mystr, 8);

return 0;

}

 

I used LCD routines from AVRLIB library which was described earlier. And I used simple schematic to display results on LCD:

Firs o all we have a part of program where is char buffer declared:

 

char mystr[16];

 

We will convert floating number to string and store in this buffer named mystr. Then we declare floating point numbers:

 

double myflt1, myflt2;

 

and do some math:

 

myflt1 = 3.14159;

myflt2 = myflt1*5.1324;

 

Now convert floating number to string and save it to our buffer by following sentence:

 

sprintf(mystr, "%.5f", myflt2);

 

This will not work if we wont show linker to use floating point library libprintf_flt.a and libm.a. Also wee need to add linker options -Wl,-u,vfprintf. It may seem hard, bet process is automated if you use Mfile generator with template:

This operation adds required linker options:

 

#---------------- Library Options ----------------

# Minimalistic printf version

PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min

 

# Floating point printf version (requires MATH_LIB = -lm below)

PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt -lm

# If this is left blank, then it will use the Standard printf version.

PRINTF_LIB = $(PRINTF_LIB_FLOAT)

#PRINTF_LIB = $(PRINTF_LIB_MIN)

#PRINTF_LIB = $(PRINTF_LIB_FLOAT)

 

You may ask what to do with AVRStudio settings, where makefile is generated automatically. Well things are simple too in this situation.

in AVRSstudio, go to Project -> Configuration Options ->setup dialog. Then go to the Libraries button down the side, and you can select libprintf_flt.a and libm.a to be used.


Then, go to the custom options , then select linker options, and then add the -Wl,-u,vfprintf switches.

And you can work with Float numbers. Of course sprintf function is generic and requires quite a lot program space. Other option would be to use dtostre() or dtostrf() as they are more
lightweight than floating-point sprintf(). Or use rprintfFloat(char numDigits, double x) function from AVRLIB library (rprintf.h).

Comments

I needed the linker options. How did you figure out what they were?

thanks a lot dude..........