printf.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /** \file printf.c
  2. * Simplified printf() and sprintf() implementation - prints formatted string to
  3. * USART (or whereever). Most common % specifiers are supported. It costs you about
  4. * 3k FLASH memory - without floating point support it uses only 1k ROM!
  5. * \author Freddie Chopin, Martin Thomas, Marten Petschke and many others
  6. * \date 16.2.2012
  7. * Get from http://www.firefly-power.de/ARM/printf.html
  8. */
  9. /******************************************************************************
  10. * chip: STM32F10x
  11. * compiler: arm-none-eabi-gcc 4.6.0
  12. *
  13. * global functions:
  14. * int printf_(const char *format, ...)
  15. * int sprintf_(char *buffer, const char *format, ...)
  16. *
  17. * STM32 specific functions:
  18. * init_UART1(void)
  19. * void putc_UART1 (char); // blocking put char, used by printf()
  20. *
  21. * local functions:
  22. * int putc_strg(int character, printf_file_t *stream)
  23. * int vfprintf_(printf_file_t *stream, const char *format, va_list arg)
  24. * void long_itoa (long val, int radix, int len, vfprintf_stream *stream)
  25. *
  26. ******************************************************************************/
  27. /*
  28. +=============================================================================+
  29. | includes
  30. +=============================================================================+
  31. */
  32. #include <stdarg.h> // (...) parameter handling
  33. /*
  34. +=============================================================================+
  35. | options
  36. +=============================================================================+
  37. */
  38. //#define INCLUDE_FLOAT // this enables float in printf() and costs you about 2kByte ROM
  39. /*
  40. +=============================================================================+
  41. | global declarations
  42. +=============================================================================+
  43. */
  44. int sprintf_(char *buffer, const char *format, ...);
  45. /*
  46. +=============================================================================+
  47. | local declarations
  48. +=============================================================================+
  49. */
  50. void putc_strg(char); // the put() function for sprintf()
  51. char *SPRINTF_buffer; //
  52. static int vfprintf_(void (*) (char), const char *format, va_list arg); //generic print
  53. void long_itoa (long, int, int, void (*) (char)); //heavily used by printf_()
  54. /*
  55. +=============================================================================+
  56. | global functions
  57. +=============================================================================+
  58. */
  59. int sprintf_(char *buffer, const char *format, ...)
  60. {
  61. va_list arg;
  62. SPRINTF_buffer=buffer; //Pointer auf einen String in Speicherzelle abspeichern
  63. va_start(arg, format);
  64. vfprintf_((&putc_strg), format, arg);
  65. va_end(arg);
  66. *SPRINTF_buffer ='\0'; // append end of string
  67. return 0;
  68. }
  69. /*
  70. +=============================================================================+
  71. | local functions
  72. +=============================================================================+
  73. */
  74. // putc_strg() is the putc() function for sprintf_()
  75. void putc_strg(char character)
  76. {
  77. *SPRINTF_buffer = (char)character; // just add the character to buffer
  78. SPRINTF_buffer++;
  79. }
  80. /*--------------------------------------------------------------------------------+
  81. * vfprintf_()
  82. * Prints a string to stream. Supports %s, %c, %d, %ld %ul %02d %i %x %lud and %%
  83. * - partly supported: long long, float (%ll %f, %F, %2.2f)
  84. * - not supported: double float and exponent (%e %g %p %o \t)
  85. *--------------------------------------------------------------------------------+
  86. */
  87. static int vfprintf_(void (*putc)(char), const char* str, va_list arp)
  88. {
  89. int d, r, w, s, l; //d=char, r = radix, w = width, s=zeros, l=long
  90. char *c; // for the while loop only
  91. #ifdef INCLUDE_FLOAT
  92. float f;
  93. long int m, mv, p, w2;
  94. #endif
  95. while ((d = *str++) != 0) {
  96. if (d != '%') {
  97. (*putc)(d);
  98. continue;
  99. }
  100. d = *str++;
  101. w = r = s = l = 0;
  102. if (d == '%') {
  103. (*putc)(d);
  104. d = *str++;
  105. }
  106. if (d == '0') {
  107. d = *str++; s = 1; //padd with zeros
  108. }
  109. while ((d >= '0')&&(d <= '9')) {
  110. w += w * 10 + (d - '0');
  111. d = *str++;
  112. }
  113. if (s) w = -w; //padd with zeros if negative
  114. #ifdef INCLUDE_FLOAT
  115. w2 = 2; //default decimal places=2
  116. if (d == '.'){
  117. d = *str++; w2 = 0; }
  118. while ((d >= '0')&&(d <= '9')) {
  119. w2 += w2 * 10 + (d - '0');
  120. d = *str++;
  121. }
  122. #endif
  123. if (d == 's') {
  124. c = va_arg(arp, char*);
  125. while (*c)
  126. (*putc)(*(c++));
  127. continue;
  128. }
  129. if (d == 'c') {
  130. (*putc)((char)va_arg(arp, int));
  131. continue;
  132. }
  133. if (d == 'u') { // %ul
  134. r = 10;
  135. d = *str++;
  136. }
  137. if (d == 'l') { // long =32bit
  138. l = 1;
  139. if (r==0) r = -10;
  140. d = *str++;
  141. }
  142. if (d =='\0') break; //avoid crashing if format string is buggy
  143. if (d == 'u') r = 10;// %lu, %llu
  144. else if (d == 'd' || d == 'i') {if (r==0) r = -10;} //can be 16 or 32bit int
  145. else if (d == 'X' || d == 'x') r = 16; // 'x' added by mthomas
  146. else if (d == 'b') r = 2;
  147. #ifdef INCLUDE_FLOAT
  148. else if (d == 'f' || d == 'F') {
  149. f=va_arg(arp, double);
  150. if (f >= 0.0) {
  151. r = 10;
  152. mv = f;
  153. m = mv;
  154. }
  155. else {
  156. r = -10;
  157. mv = f;
  158. f = -f;
  159. m = f; // f and m are always positive
  160. }
  161. long_itoa(mv, r, w, (putc));
  162. if (w2!=0) {
  163. putc('.');
  164. f=f-m;
  165. w=-w2; p=1;
  166. while (w2--) p = p*10;
  167. m=f*p;
  168. long_itoa(m, 10, w, (putc));
  169. }
  170. l=3; //do not continue with long
  171. }
  172. #endif
  173. else str--; // normal character
  174. if (r==0) continue; //
  175. if (l==0) {
  176. if (r > 0){ //unsigned
  177. long_itoa((unsigned long)va_arg(arp, int), r, w, (putc)); //needed for 16bit int, no harm to 32bit int
  178. }
  179. else //signed
  180. long_itoa((long)va_arg(arp, int), r, w, (putc));
  181. } else if (l==1){ // long =32bit
  182. long_itoa((long)va_arg(arp, long), r, w, (putc)); //no matter if signed or unsigned
  183. }
  184. }
  185. return 0;
  186. }
  187. void long_itoa (long val, int radix, int len, void (*putc) (char))
  188. {
  189. char c, sgn = 0, pad = ' ';
  190. char s[20];
  191. int i = 0;
  192. if (radix < 0) {
  193. radix = -radix;
  194. if (val < 0) {
  195. val = -val;
  196. sgn = '-';
  197. }
  198. }
  199. if (len < 0) {
  200. len = -len;
  201. pad = '0';
  202. }
  203. if (len > 20) return;
  204. do {
  205. c = (char)((unsigned long)val % radix); //cast!
  206. if (c >= 10) c += ('A'-10); //ABCDEF
  207. else c += '0'; //0123456789
  208. s[i++] = c;
  209. val = (unsigned long)val /radix; //cast!
  210. } while (val);
  211. if ((sgn!=0) && (pad!='0')) s[i++] = sgn;
  212. while (i < len)
  213. s[i++] = pad;
  214. if ((sgn!=0) && (pad=='0')) s[i++] = sgn;
  215. do
  216. (*putc)(s[--i]);
  217. while (i);
  218. }
  219. /******************************************************************************
  220. * END OF FILE
  221. ******************************************************************************/