Hi all. On example for LPC are used function rprintf to serial port . But I can't print float value (double). can some help??? regards
I just downloaded the examples and looked at the code and it quite clearly says in the boiler-plate comment: ------------ // Todo: // %f, %F for floating point numbers ------------ It is a 'reduced' printf after all and fp handling would increase the size. Use the standard printf if you need full functionality. Clifford
Sevc Dominik wrote:
> But I can't print float value (double).
The rprintf in the Michael Wolf's Project in the thread "[ANN]
AT91SAM7S-128 USB MSD Example" includes a rprintf with FP support.
(While most of the projects seems to be under GPL license the lincense
for the rprintf-code seems to be BSD or BSD-compatible and so reather
unrestricted)
Sevc Dominik wrote: > Hi all. > On example for LPC are used function rprintf to serial port . > But I can't print float value (double). > can some help??? > regards You are welcome to use following files: rprintf.h: ============== #ifndef __PRINTF_H #define __PRINTF_H extern void rputs(char const *txt); extern void rprintf(char const *fmt0, ...); #endif rprintf.c: =========== //###################################################################### ######## // (r)printf.c // // code based on sprintf() from gcctest9.c by Volker Oth // // Changes made by Holger Klabunde: // Now takes format strings from FLASH (was into RAM ! before) // Fixed bug for %i, %I. u_val was used before it had the right value // Added %d, %D (is same as %i, %I) // Support for long variables %li, %ld, %Lu, %LX .... // %x, %X now gives upper case hex characters A,B,C,D,E,F // Output can be redirected in a single function: myputchar() // Make printf() smaller by commenting out a few #defines // Added some SPACE and ZERO padding %02x or % 3u up to 9 characters // // Changes made by Martin Thomas: // LPC2000 port using the R O Software UART-Interface (see myputchar) // ARM7S port using minimal uart interface // reverted Klabundes "from flash" since only useful for AVR "Harvard" // // Changes made by Sławomir Wilczewski: // - added %f, %F for floating point numbers conversion // - accuracy max 1 digit, width max 2 digits in format string (ex: % 10.4f) // - max number of characters (incl. sign): to fit into buffer SCRATCH size // - floating point conversion code size is 6.5kB in .text area // //###################################################################### ######## #include <stdarg.h> #include <string.h> #include "rprintf.h" #define SCRATCH 12 //32Bits go up to 4GB + 1 Byte for \0 //Spare some program space by making a comment of all not used format flag lines #define USE_LONG // %lx, %Lu and so on, else only 16 bit integer is allowed //#define USE_OCTAL // %o, %O Octal output. Who needs this ? #define USE_STRING // %s, %S Strings as parameters #define USE_CHAR // %c, %C Chars as parameters #define USE_INTEGER // %i, %I Remove this format flag. %d, %D does the same #define USE_HEX // %x, %X Hexadezimal output #define USE_UPPERHEX // %x, %X outputs A,B,C... else a,b,c... #ifndef USE_HEX #undef USE_UPPERHEX // ;) #endif #define USE_UPPER // uncommenting this removes %C,%D,%I,%O,%S,%U,%X and %L.. // only lowercase format flags are used #define PADDING //SPACE and ZERO padding #define USE_FLOAT // %f %F floating point numbers as parameters. //float params #ifdef USE_FLOAT #define LEFT_ALIGN 0x01 #define SHOW_SIGN 0x02 #define MINUS_ONLY 0x04 #define SHOW_ALTERNATE 0x08 //always display dot #define NEGATIVE 0x10 //defaults: #define DFLT_F_ACCURACY 2 #define DFLT_F_WIDTH 6 #define DFLT_F_FILL ' ' static char * strrev( char * pa ); unsigned char* ftoa( float f, char const *format, unsigned char *ucaFloat ); #endif #include "lcd.h" static void myputchar( unsigned char c ){ LCDPreter( c ); } void rprintf( char const *format, ... ){ unsigned char scratch[SCRATCH]; unsigned char format_flag; unsigned short base; unsigned char *ptr; unsigned char issigned=0; va_list ap; #ifdef USE_LONG unsigned char islong=0; unsigned long u_val=0; long s_val=0; #else unsigned int u_val=0; int s_val=0; #endif #ifdef USE_FLOAT double f_val = 0; char const * pStr; #endif unsigned char fill; unsigned char width; va_start (ap, format); for (;;){ while ((format_flag = *(format++)) != '%'){ // Until '%' or '\0' if (!format_flag){va_end (ap); return;} myputchar(format_flag); } #ifdef USE_FLOAT pStr = format; fill = 0; while( *pStr ){ if( ( *pStr == 'l' ) || ( *pStr == 'L' ) ) break; if( ( *pStr == 'o' ) || ( *pStr == 'O' ) ) break; if( ( *pStr == 's' ) || ( *pStr == 'S' ) ) break; if( ( *pStr == 'c' ) || ( *pStr == 'C' ) ) break; if( ( *pStr == 'i' ) || ( *pStr == 'I' ) ) break; if( ( *pStr == 'd' ) || ( *pStr == 'D' ) ) break; if( ( *pStr == 'u' ) || ( *pStr == 'U' ) ) break; if( ( *pStr == 'x' ) || ( *pStr == 'X' ) ) break; if( ( *pStr == 'f' ) || ( *pStr == 'F' ) ){ fill = 1; f_val = va_arg( ap, double ); ptr = ftoa( (float)f_val, format, scratch ); format = ++pStr; while( *ptr ) { myputchar( *ptr ); ptr++; } break; } pStr++; } if( fill ) continue; #endif issigned=0; //default unsigned base = 10; format_flag = *format++; //get char after '%' #ifdef PADDING width=0; //no formatting fill=0; //no formatting if(format_flag=='0' || format_flag==' ') //SPACE or ZERO padding ? { fill=format_flag; format_flag = *format++; //get char after padding char if(format_flag>='0' && format_flag<='9') { width=format_flag-'0'; format_flag = *format++; //get char after width char } } #endif #ifdef USE_LONG islong=0; //default int value #ifdef USE_UPPER if(format_flag=='l' || format_flag=='L') //Long value #else if(format_flag=='l') //Long value #endif { islong=1; format_flag = *format++; //get char after 'l' or 'L' } #endif switch (format_flag) { #ifdef USE_CHAR case 'c': #ifdef USE_UPPER case 'C': #endif format_flag = va_arg(ap,int); // no break -> run into default #endif default: myputchar(format_flag); continue; #ifdef USE_STRING #ifdef USE_UPPER case 'S': #endif case 's': ptr = (unsigned char*)va_arg(ap,char *); while(*ptr) { myputchar(*ptr); ptr++; } continue; #endif #ifdef USE_OCTAL case 'o': #ifdef USE_UPPER case 'O': #endif base = 8; myputchar('0'); goto CONVERSION_LOOP; #endif #ifdef USE_INTEGER //don't use %i, is same as %d case 'i': #ifdef USE_UPPER case 'I': #endif #endif case 'd': #ifdef USE_UPPER case 'D': #endif issigned=1; // no break -> run into next case case 'u': #ifdef USE_UPPER case 'U': #endif //don't insert some case below this if USE_HEX is undefined ! //or put goto CONVERSION_LOOP; before next case. #ifdef USE_HEX goto CONVERSION_LOOP; case 'x': #ifdef USE_UPPER case 'X': #endif base = 16; #endif CONVERSION_LOOP: if(issigned) //Signed types { #ifdef USE_LONG if(islong) { s_val = va_arg(ap,long); } else { s_val = va_arg(ap,int); } #else s_val = va_arg(ap,int); #endif if(s_val < 0) //Value negativ ? { s_val = - s_val; //Make it positiv myputchar('-'); //Output sign } u_val = (unsigned long)s_val; } else //Unsigned types { #ifdef USE_LONG if(islong) { u_val = va_arg(ap,unsigned long); } else { u_val = va_arg(ap,unsigned int); } #else u_val = va_arg(ap,unsigned int); #endif } ptr = scratch + SCRATCH; *--ptr = 0; do { char ch = u_val % base + '0'; #ifdef USE_HEX if (ch > '9') { ch += 'a' - '9' - 1; #ifdef USE_UPPERHEX ch-=0x20; #endif } #endif *--ptr = ch; u_val /= base; #ifdef PADDING if(width) width--; //calculate number of padding chars #endif } while (u_val); #ifdef PADDING while(width--) *--ptr = fill; //insert padding chars #endif while(*ptr) { myputchar(*ptr); ptr++; } } } } #ifdef USE_FLOAT static char* strrev( char *pa ){ char * pStr; char c; int i, len; pStr = pa; len = 0; while( *pStr++ ) ++len; if( len < 2 ) return pa; for( i = 0; i < len / 2; ++i ){ c = *( pa + i ); *( pa + i ) = *( pa + len - 1 - i ); *( pa + len - 1 - i ) = c; } return pa; } #endif #ifdef USE_FLOAT unsigned char* ftoa( float f, char const *format, unsigned char *ucaFloat ){ char cFlag, cWidth = DFLT_F_WIDTH, cAccuracy = DFLT_F_ACCURACY, * pStr, // caTemp[ 82 ], caTemp[ 2 * SCRATCH ], caFillChar[ 2 ] = " "; //space or zero char const * pcStr; unsigned long i, j; unsigned long long lNumber; //find accuracy or use default pcStr = --format; while( *pcStr++ ){ if( ( *pcStr == 'f' ) || ( *pcStr == 'F' ) ) break; if( *pcStr == '.' ){ //assume 1 digit for accuracy if( ( *( pcStr + 1 ) == 'f' ) || ( *( pcStr + 1 ) == 'F' ) ) cAccuracy = 0; else cAccuracy = *( pcStr + 1 ) - '0'; break; } } //find width or use default. Max 2 digits. cFlag = 0; pcStr = format; while( *pcStr++ ){ if( ( *pcStr == 'f' ) || ( *pcStr == 'F' ) || ( *pcStr == '.' ) ) break; if( ( *pcStr >= '0' ) && ( *pcStr <= '9' ) ){ if( ( *pcStr == '0' ) && ( cFlag == 0 )){ //leading zero (fill char) *caFillChar = '0'; *( caFillChar + 1 ) = 0; continue; } *( caTemp + cFlag ) = *pcStr; ++cFlag; } } *( caTemp + cFlag ) = 0; if( strlen( caTemp ) > 0 ){ strrev( caTemp ); cWidth = 0; i = 1; pStr = &caTemp[ 0 ]; while( *pStr ){ cWidth += ( *pStr - '0' ) * i; i *= 10; pStr++; } } //special format characters cFlag = 0; pcStr = format; while( *pcStr++ ){ if( ( *pcStr == 'f' ) || ( *pcStr == 'F' ) || ( *pcStr == '.' ) ) break; if( ( *pcStr >= '0' ) && ( *pcStr <= '9' ) ) break; if( *pcStr == '-' ) cFlag |= LEFT_ALIGN; if( *pcStr == '+' ) cFlag |= SHOW_SIGN; if( *pcStr == ' ' ) cFlag |= MINUS_ONLY; if( *pcStr == '#' ) cFlag |= SHOW_ALTERNATE; } //to do: eliminate invalid / useless format combinations if( f < 0 ){ cFlag |= NEGATIVE; f = -f; } if( cAccuracy > 0 ) for( i = 0; i < cAccuracy; ++i ) f *= 10; lNumber = (unsigned long long)( f ); if( ( ( (unsigned long long)( f * 10 ) ) % 10 ) >= 5 ) lNumber++; //rounding //conversion to ascii pStr = &caTemp[ 0 ]; *pStr = 0; do{ *pStr++ = ( lNumber % 10 ) + '0'; lNumber /= 10; } while( lNumber ); *pStr = 0; //handling small numbers if( ( j = strlen( caTemp ) ) <= cAccuracy ){ for( i = 0; i < cAccuracy - j; ++i ){ *( caTemp + j + i ) = '0'; } *( caTemp + cAccuracy ) = '0'; //ensure 0 before dot *( caTemp + cAccuracy + 1 ) = 0; } //insert dot i = strlen( caTemp ); *( caTemp + i + 1 ) = 0; for( j = 0; j < i - cAccuracy; ++j ) *( caTemp + i - j ) = *( caTemp + i - j - 1 ); *( caTemp + cAccuracy ) = '.'; //check size if( ( strlen( caTemp ) > SCRATCH - 2 ) // one char for sign || ( cWidth > SCRATCH - 2 ) ) { *ucaFloat = 0; *ucaFloat = '?'; *( ucaFloat + 1 ) = 0; return ucaFloat; } //sign processing *ucaFloat = 0; //show sign with 0 ?? if( cFlag & NEGATIVE ){ *ucaFloat = '-'; *( ucaFloat + 1 ) = 0; if( cWidth > 1 ) --cWidth; //include sign into string width } else{ if( cFlag & SHOW_SIGN ){ *ucaFloat = '+'; *( ucaFloat + 1 ) = 0; if( cWidth > 1 ) --cWidth; } if( cFlag & MINUS_ONLY ){ //insert space in this case *ucaFloat = ' '; *( ucaFloat + 1 ) = 0; if( cWidth > 1 ) --cWidth; } } //formating if( cFlag & SHOW_ALTERNATE ){}; //dot always inserted //fill character. if( ( cFlag & LEFT_ALIGN ) == 0 ){ //leading fill chars while( strlen( caTemp ) < cWidth ) strcat( caTemp, caFillChar ); } strrev( caTemp ); if( cFlag & LEFT_ALIGN ){ while( strlen( caTemp ) < cWidth ) strcat( caTemp, caFillChar ); } strcat( (char*)ucaFloat, caTemp ); return ucaFloat; } #endif
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.