123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /** \file printf.c
- * Simplified printf() and sprintf() implementation - prints formatted string to
- * USART (or whereever). Most common % specifiers are supported. It costs you about
- * 3k FLASH memory - without floating point support it uses only 1k ROM!
- * \author Freddie Chopin, Martin Thomas, Marten Petschke and many others
- * \date 16.2.2012
- * Get from http://www.firefly-power.de/ARM/printf.html
- */
- /******************************************************************************
- * chip: STM32F10x
- * compiler: arm-none-eabi-gcc 4.6.0
- *
- * global functions:
- * int printf_(const char *format, ...)
- * int sprintf_(char *buffer, const char *format, ...)
- *
- * STM32 specific functions:
- * init_UART1(void)
- * void putc_UART1 (char); // blocking put char, used by printf()
- *
- * local functions:
- * int putc_strg(int character, printf_file_t *stream)
- * int vfprintf_(printf_file_t *stream, const char *format, va_list arg)
- * void long_itoa (long val, int radix, int len, vfprintf_stream *stream)
- *
- ******************************************************************************/
- /*
- +=============================================================================+
- | includes
- +=============================================================================+
- */
- #include <stdarg.h> // (...) parameter handling
- /*
- +=============================================================================+
- | options
- +=============================================================================+
- */
- //#define INCLUDE_FLOAT // this enables float in printf() and costs you about 2kByte ROM
- /*
- +=============================================================================+
- | global declarations
- +=============================================================================+
- */
- int sprintf_(char *buffer, const char *format, ...);
- /*
- +=============================================================================+
- | local declarations
- +=============================================================================+
- */
- void putc_strg(char); // the put() function for sprintf()
- char *SPRINTF_buffer; //
- static int vfprintf_(void (*) (char), const char *format, va_list arg); //generic print
- void long_itoa (long, int, int, void (*) (char)); //heavily used by printf_()
- /*
- +=============================================================================+
- | global functions
- +=============================================================================+
- */
- int sprintf_(char *buffer, const char *format, ...)
- {
- va_list arg;
- SPRINTF_buffer=buffer; //Pointer auf einen String in Speicherzelle abspeichern
- va_start(arg, format);
- vfprintf_((&putc_strg), format, arg);
- va_end(arg);
- *SPRINTF_buffer ='\0'; // append end of string
- return 0;
- }
- /*
- +=============================================================================+
- | local functions
- +=============================================================================+
- */
- // putc_strg() is the putc() function for sprintf_()
- void putc_strg(char character)
- {
- *SPRINTF_buffer = (char)character; // just add the character to buffer
- SPRINTF_buffer++;
- }
- /*--------------------------------------------------------------------------------+
- * vfprintf_()
- * Prints a string to stream. Supports %s, %c, %d, %ld %ul %02d %i %x %lud and %%
- * - partly supported: long long, float (%ll %f, %F, %2.2f)
- * - not supported: double float and exponent (%e %g %p %o \t)
- *--------------------------------------------------------------------------------+
- */
- static int vfprintf_(void (*putc)(char), const char* str, va_list arp)
- {
- int d, r, w, s, l; //d=char, r = radix, w = width, s=zeros, l=long
- char *c; // for the while loop only
- #ifdef INCLUDE_FLOAT
- float f;
- long int m, mv, p, w2;
- #endif
- while ((d = *str++) != 0) {
- if (d != '%') {
- (*putc)(d);
- continue;
- }
- d = *str++;
- w = r = s = l = 0;
- if (d == '%') {
- (*putc)(d);
- d = *str++;
- }
- if (d == '0') {
- d = *str++; s = 1; //padd with zeros
- }
- while ((d >= '0')&&(d <= '9')) {
- w += w * 10 + (d - '0');
- d = *str++;
- }
- if (s) w = -w; //padd with zeros if negative
- #ifdef INCLUDE_FLOAT
- w2 = 2; //default decimal places=2
- if (d == '.'){
- d = *str++; w2 = 0; }
- while ((d >= '0')&&(d <= '9')) {
- w2 += w2 * 10 + (d - '0');
- d = *str++;
- }
- #endif
- if (d == 's') {
- c = va_arg(arp, char*);
- while (*c)
- (*putc)(*(c++));
- continue;
- }
- if (d == 'c') {
- (*putc)((char)va_arg(arp, int));
- continue;
- }
- if (d == 'u') { // %ul
- r = 10;
- d = *str++;
- }
- if (d == 'l') { // long =32bit
- l = 1;
- if (r==0) r = -10;
- d = *str++;
- }
- if (d =='\0') break; //avoid crashing if format string is buggy
- if (d == 'u') r = 10;// %lu, %llu
- else if (d == 'd' || d == 'i') {if (r==0) r = -10;} //can be 16 or 32bit int
- else if (d == 'X' || d == 'x') r = 16; // 'x' added by mthomas
- else if (d == 'b') r = 2;
- #ifdef INCLUDE_FLOAT
- else if (d == 'f' || d == 'F') {
- f=va_arg(arp, double);
- if (f >= 0.0) {
- r = 10;
- mv = f;
- m = mv;
- }
- else {
- r = -10;
- mv = f;
- f = -f;
- m = f; // f and m are always positive
- }
- long_itoa(mv, r, w, (putc));
- if (w2!=0) {
- putc('.');
- f=f-m;
- w=-w2; p=1;
- while (w2--) p = p*10;
- m=f*p;
- long_itoa(m, 10, w, (putc));
- }
- l=3; //do not continue with long
- }
- #endif
- else str--; // normal character
- if (r==0) continue; //
- if (l==0) {
- if (r > 0){ //unsigned
- long_itoa((unsigned long)va_arg(arp, int), r, w, (putc)); //needed for 16bit int, no harm to 32bit int
- }
- else //signed
- long_itoa((long)va_arg(arp, int), r, w, (putc));
- } else if (l==1){ // long =32bit
- long_itoa((long)va_arg(arp, long), r, w, (putc)); //no matter if signed or unsigned
- }
- }
- return 0;
- }
- void long_itoa (long val, int radix, int len, void (*putc) (char))
- {
- char c, sgn = 0, pad = ' ';
- char s[20];
- int i = 0;
- if (radix < 0) {
- radix = -radix;
- if (val < 0) {
- val = -val;
- sgn = '-';
- }
- }
- if (len < 0) {
- len = -len;
- pad = '0';
- }
- if (len > 20) return;
- do {
- c = (char)((unsigned long)val % radix); //cast!
- if (c >= 10) c += ('A'-10); //ABCDEF
- else c += '0'; //0123456789
- s[i++] = c;
- val = (unsigned long)val /radix; //cast!
- } while (val);
- if ((sgn!=0) && (pad!='0')) s[i++] = sgn;
- while (i < len)
- s[i++] = pad;
- if ((sgn!=0) && (pad=='0')) s[i++] = sgn;
- do
- (*putc)(s[--i]);
- while (i);
- }
- /******************************************************************************
- * END OF FILE
- ******************************************************************************/
|