Forum: Compiler & IDEs STM32F4 printf für float implementieren


von Stm M. (stmfresser)


Lesenswert?

Hallo Leute,

ich möchte printf Funktion für float Zahl auf einen STM32F407 Discovery 
Board hinzukriegen.
wenn ich mal printf("float Zahl %f \n", 123.0f) eingebe, empfange ich 
über USART gar nichts.

Kann mir jemand helfen, wie ich den printf.c Datei für float anpasse.

Vielen Dank im Voraus,

Gruß Chu
1
/**************************************************************************//*****
2
 * @file     printf.c
3
 * @brief    Implementation of several stdio.h methods, such as printf(), 
4
 *           sprintf() and so on. This reduces the memory footprint of the
5
 *           binary when using those methods, compared to the libc implementation.
6
 ********************************************************************************/
7
#include <stdio.h>
8
#include <stdarg.h>
9
#include <stm32f4xx_usart.h>
10
11
12
/**
13
 * @brief  Transmit a char, if you want to use printf(), 
14
 *         you need implement this function
15
 *
16
 * @param  pStr  Storage string.
17
 * @param  c    Character to write.
18
 */
19
void PrintChar(char c)
20
{
21
    if (c == '\n')  {
22
      while (!(USART1->SR & 0x0080));
23
      USART1->DR = 0x0D;
24
    }
25
     while (!(USART1->SR & 0x0080));
26
    USART1->DR = (c & 0x1FF);
27
}
28
29
/** Maximum string size allowed (in bytes). */
30
#define MAX_STRING_SIZE         100
31
32
33
/** Required for proper compilation. */
34
struct _reent r = {0, (FILE *) 0, (FILE *) 1, (FILE *) 0};
35
//struct _reent *_impure_ptr = &r;
36
37
/**
38
 * @brief  Writes a character inside the given string. Returns 1.
39
 *
40
 * @param  pStr  Storage string.
41
 * @param  c    Character to write.
42
 */
43
signed int PutChar(char *pStr, char c)
44
{
45
    *pStr = c;
46
    return 1;
47
}
48
49
50
/**
51
 * @brief  Writes a string inside the given string.
52
 *
53
 * @param  pStr     Storage string.
54
 * @param  pSource  Source string.
55
 * @return  The size of the written
56
 */
57
signed int PutString(char *pStr, const char *pSource)
58
{
59
    signed int num = 0;
60
61
    while (*pSource != 0) {
62
63
        *pStr++ = *pSource++;
64
        num++;
65
    }
66
67
    return num;
68
}
69
70
71
/**
72
 * @brief  Writes an unsigned int inside the given string, using the provided fill &
73
 *         width parameters.
74
 *
75
 * @param  pStr  Storage string.
76
 * @param  fill  Fill character.
77
 * @param  width  Minimum integer width.
78
 * @param  value  Integer value.   
79
 */
80
signed int PutUnsignedInt(
81
    char *pStr,
82
    char fill,
83
    signed int width,
84
    unsigned int value)
85
{
86
    signed int num = 0;
87
88
    /* Take current digit into account when calculating width */
89
    width--;
90
91
    /* Recursively write upper digits */
92
    if ((value / 10) > 0) {
93
94
        num = PutUnsignedInt(pStr, fill, width, value / 10);
95
        pStr += num;
96
    }
97
    
98
    /* Write filler characters */
99
    else {
100
101
        while (width > 0) {
102
103
            PutChar(pStr, fill);
104
            pStr++;
105
            num++;
106
            width--;
107
        }
108
    }
109
110
    /* Write lower digit */
111
    num += PutChar(pStr, (value % 10) + '0');
112
113
    return num;
114
}
115
116
117
/**
118
 * @brief  Writes a signed int inside the given string, using the provided fill & width
119
 *         parameters.
120
 *
121
 * @param pStr   Storage string.
122
 * @param fill   Fill character.
123
 * @param width  Minimum integer width.
124
 * @param value  Signed integer value.
125
 */
126
signed int PutSignedInt(
127
    char *pStr,
128
    char fill,
129
    signed int width,
130
    signed int value)
131
{
132
    signed int num = 0;
133
    unsigned int absolute;
134
135
    /* Compute absolute value */
136
    if (value < 0) {
137
138
        absolute = -value;
139
    }
140
    else {
141
142
        absolute = value;
143
    }
144
145
    /* Take current digit into account when calculating width */
146
    width--;
147
148
    /* Recursively write upper digits */
149
    if ((absolute / 10) > 0) {
150
151
        if (value < 0) {
152
        
153
            num = PutSignedInt(pStr, fill, width, -(absolute / 10));
154
        }
155
        else {
156
157
            num = PutSignedInt(pStr, fill, width, absolute / 10);
158
        }
159
        pStr += num;
160
    }
161
    else {
162
163
        /* Reserve space for sign */
164
        if (value < 0) {
165
166
            width--;
167
        }
168
169
        /* Write filler characters */
170
        while (width > 0) {
171
172
            PutChar(pStr, fill);
173
            pStr++;
174
            num++;
175
            width--;
176
        }
177
178
        /* Write sign */
179
        if (value < 0) {
180
181
            num += PutChar(pStr, '-');
182
            pStr++;
183
        }
184
    }
185
186
    /* Write lower digit */
187
    num += PutChar(pStr, (absolute % 10) + '0');
188
189
    return num;
190
}
191
192
193
/**
194
 * @brief  Writes an hexadecimal value into a string, using the given fill, width &
195
 *         capital parameters.
196
 *
197
 * @param pStr   Storage string.
198
 * @param fill   Fill character.
199
 * @param width  Minimum integer width.
200
 * @param maj    Indicates if the letters must be printed in lower- or upper-case.
201
 * @param value  Hexadecimal value.
202
 *
203
 * @return  The number of char written
204
 */
205
signed int PutHexa(
206
    char *pStr,
207
    char fill,
208
    signed int width,
209
    unsigned char maj,
210
    unsigned int value)
211
{
212
    signed int num = 0;
213
214
    /* Decrement width */
215
    width--;
216
217
    /* Recursively output upper digits */
218
    if ((value >> 4) > 0) {
219
220
        num += PutHexa(pStr, fill, width, maj, value >> 4);
221
        pStr += num;
222
    }
223
    /* Write filler chars */
224
    else {
225
226
        while (width > 0) {
227
228
            PutChar(pStr, fill);
229
            pStr++;
230
            num++;
231
            width--;
232
        }
233
    }
234
235
    /* Write current digit */
236
    if ((value & 0xF) < 10) {
237
238
        PutChar(pStr, (value & 0xF) + '0');
239
    }
240
    else if (maj) {
241
242
        PutChar(pStr, (value & 0xF) - 10 + 'A');
243
    }
244
    else {
245
246
        PutChar(pStr, (value & 0xF) - 10 + 'a');
247
    }
248
    num++;
249
250
    return num;
251
}
252
253
254
255
/* Global Functions ----------------------------------------------------------- */
256
257
258
/**
259
 * @brief  Stores the result of a formatted string into another string. Format
260
 *         arguments are given in a va_list instance.
261
 *
262
 * @param pStr    Destination string.
263
 * @param length  Length of Destination string.
264
 * @param pFormat Format string.
265
 * @param ap      Argument list.
266
 *
267
 * @return  The number of characters written.
268
 */
269
signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
270
{
271
    char          fill;
272
    unsigned char width;
273
    signed int    num = 0;
274
    signed int    size = 0;
275
276
    /* Clear the string */
277
    if (pStr) {
278
279
        *pStr = 0;
280
    }
281
282
    /* Phase string */
283
    while (*pFormat != 0 && size < length) {
284
285
        /* Normal character */
286
        if (*pFormat != '%') {
287
288
            *pStr++ = *pFormat++;
289
            size++;
290
        }
291
        /* Escaped '%' */
292
        else if (*(pFormat+1) == '%') {
293
294
            *pStr++ = '%';
295
            pFormat += 2;
296
            size++;
297
        }
298
        /* Token delimiter */
299
        else {
300
301
            fill = ' ';
302
            width = 0;
303
            pFormat++;
304
305
            /* Parse filler */
306
            if (*pFormat == '0') {
307
308
                fill = '0';
309
                pFormat++;
310
            }
311
312
            /* Parse width */
313
            while ((*pFormat >= '0') && (*pFormat <= '9')) {
314
        
315
                width = (width*10) + *pFormat-'0';
316
                pFormat++;
317
            }
318
319
            /* Check if there is enough space */
320
            if (size + width > length) {
321
322
                width = length - size;
323
            }
324
        
325
            /* Parse type */
326
            switch (*pFormat) {
327
            case 'd': 
328
            case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
329
            case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
330
            case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
331
            case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
332
            case 's': num = PutString(pStr, va_arg(ap, char *)); break;
333
            case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break;
334
            default:
335
                return EOF;
336
            }
337
338
            pFormat++;
339
            pStr += num;
340
            size += num;
341
        }
342
    }
343
344
    /* NULL-terminated (final \0 is not counted) */
345
    if (size < length) {
346
347
        *pStr = 0;
348
    }
349
    else {
350
351
        *(--pStr) = 0;
352
        size--;
353
    }
354
355
    return size;
356
}
357
358
359
/**
360
 * @brief  Stores the result of a formatted string into another string. Format
361
 *         arguments are given in a va_list instance.
362
 *
363
 * @param pStr    Destination string.
364
 * @param length  Length of Destination string.
365
 * @param pFormat Format string.
366
 * @param ...     Other arguments
367
 *
368
 * @return  The number of characters written.
369
 */
370
signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
371
{
372
    va_list    ap;
373
    signed int rc;
374
375
    va_start(ap, pFormat);
376
    rc = vsnprintf(pString, length, pFormat, ap);
377
    va_end(ap);
378
379
    return rc;
380
}
381
382
383
/**
384
 * @brief  Stores the result of a formatted string into another string. Format
385
 *         arguments are given in a va_list instance.
386
 *
387
 * @param pString  Destination string.
388
 * @param length   Length of Destination string.
389
 * @param pFormat  Format string.
390
 * @param ap       Argument list.
391
 *
392
 * @return  The number of characters written.
393
 */
394
signed int vsprintf(char *pString, const char *pFormat, va_list ap)
395
{
396
   return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
397
}
398
399
/**
400
 * @brief  Outputs a formatted string on the given stream. Format arguments are given
401
 *         in a va_list instance.
402
 *
403
 * @param pStream  Output stream.
404
 * @param pFormat  Format string
405
 * @param ap       Argument list. 
406
 */
407
signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
408
{
409
    char pStr[MAX_STRING_SIZE];
410
    char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r";
411
412
    /* Write formatted string in buffer */
413
    if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
414
415
        fputs(pError, stderr);
416
        while (1); /* Increase MAX_STRING_SIZE */
417
    }
418
419
    /* Display string */
420
    return fputs(pStr, pStream);
421
}
422
423
424
/**
425
 * @brief  Outputs a formatted string on the DBGU stream. Format arguments are given
426
 *         in a va_list instance.
427
 *
428
 * @param pFormat  Format string.
429
 * @param ap  Argument list.
430
 */
431
signed int vprintf(const char *pFormat, va_list ap)
432
{
433
    return vfprintf(stdout, pFormat, ap);
434
}
435
436
437
/**
438
 * @brief  Outputs a formatted string on the given stream, using a variable 
439
 *         number of arguments.
440
 *
441
 * @param pStream  Output stream.
442
 * @param pFormat  Format string.
443
 */
444
signed int fprintf(FILE *pStream, const char *pFormat, ...)
445
{
446
    va_list ap;
447
    signed int result;
448
449
    /* Forward call to vfprintf */
450
    va_start(ap, pFormat);
451
    result = vfprintf(pStream, pFormat, ap);
452
    va_end(ap);
453
454
    return result;
455
}
456
457
458
/**
459
 * @brief  Outputs a formatted string on the DBGU stream, using a variable number of
460
 *         arguments.
461
 *
462
 * @param  pFormat  Format string.
463
 */
464
signed int printf(const char *pFormat, ...)
465
{
466
    va_list ap;
467
    signed int result;
468
469
    /* Forward call to vprintf */
470
    va_start(ap, pFormat);
471
    result = vprintf(pFormat, ap);
472
    va_end(ap);
473
474
    return result;
475
}
476
477
478
/**
479
 * @brief  Writes a formatted string inside another string.
480
 *
481
 * @param pStr     torage string.
482
 * @param pFormat  Format string.
483
 */
484
signed int sprintf(char *pStr, const char *pFormat, ...)
485
{
486
    va_list ap;
487
    signed int result;
488
489
    // Forward call to vsprintf
490
    va_start(ap, pFormat);
491
    result = vsprintf(pStr, pFormat, ap);
492
    va_end(ap);
493
494
    return result;
495
}
496
497
498
/**
499
 * @brief  Outputs a string on stdout.
500
 *
501
 * @param pStr  String to output. 
502
 */
503
signed int puts(const char *pStr)
504
{
505
    return fputs(pStr, stdout);
506
}
507
508
509
/**
510
 * @brief  Implementation of fputc using the DBGU as the standard output. Required
511
 *         for printf().
512
 *
513
 * @param c        Character to write.
514
 * @param pStream  Output stream.
515
 * @param The character written if successful, or -1 if the output stream is
516
 *        not stdout or stderr.
517
 */
518
signed int fputc(signed int c, FILE *pStream)
519
{
520
    if ((pStream == stdout) || (pStream == stderr)) {
521
522
      PrintChar(c);
523
524
        return c;
525
    }
526
    else {
527
528
        return EOF;
529
    }
530
}
531
532
533
/**
534
 * @brief  Implementation of fputs using the DBGU as the standard output. Required
535
 *         for printf().
536
 *
537
 * @param pStr     String to write.
538
 * @param pStream  Output stream.
539
 *
540
 * @return  Number of characters written if successful, or -1 if the output
541
 *          stream is not stdout or stderr.
542
 */
543
signed int fputs(const char *pStr, FILE *pStream)
544
{
545
    signed int num = 0;
546
547
    while (*pStr != 0) {
548
549
        if (fputc(*pStr, pStream) == -1) {
550
551
            return -1;
552
        }
553
        num++;
554
        pStr++;
555
    }
556
557
    return num;
558
}
559
560
/* --------------------------------- End Of File ------------------------------ */

von Irgendwer (Gast)


Lesenswert?

Stm Mc schrieb:
> /* Parse type */
>             switch (*pFormat) {
>             case 'd':
>             case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap,
> signed int)); break;
>             case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap,
> unsigned int)); break;
>             case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap,
> unsigned int)); break;
>             case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap,
> unsigned int)); break;
>             case 's': num = PutString(pStr, va_arg(ap, char *)); break;
>             case 'c': num = PutChar(pStr, va_arg(ap, unsigned int));
> break;

Na dann fang doch einfach mal damit an dir eine PutEigeneFloat zu 
basteln...

von PittyJ (Gast)


Lesenswert?

Ja, du musst bei den cases in vsnprintf() den
     case 'f':
implementieren.
Also das Bitmuster der Floating Point Zahl nehmen, und den in sinnvolle 
ASCII-Wert umwandeln.

Siehe dazu auch
http://de.wikipedia.org/wiki/IEEE_754

von Uwe B. (derexponent)


Lesenswert?

hier ein fertiger Beispiel-Code :
1
#include "stm32_ub_string.h"
2
3
4
//--------------------------------------------------------------
5
// wandelt eine Float Zahl in einen String als Dezimahl Zahl
6
// ergebnis steht dann in "STRING_BUF"
7
// Float muss zwischen -32767 und +32767 liegen
8
//--------------------------------------------------------------
9
void UB_String_FloatToDezStr(float wert)
10
{
11
  int16_t vorkomma;
12
  uint16_t nachkomma;
13
  float rest;
14
15
  if((wert>32767) || (wert<-32767)) {
16
    // zahl zu groß oder zu klein
17
    sprintf(STRING_BUF,"%s","OVF");
18
    return;
19
  }
20
21
  vorkomma=(int16_t)(wert);
22
  if(wert>=0) {
23
    rest = wert-(float)(vorkomma);
24
  }
25
  else {
26
    rest = (float)(vorkomma)-wert;
27
  }
28
  nachkomma = (uint16_t)(rest*(float)(STRING_FLOAT_FAKTOR)+0.5);
29
30
  sprintf(STRING_BUF,STRING_FLOAT_FORMAT,vorkomma,nachkomma);
31
}

1
#include "stm32f4xx.h"
2
#include <stdio.h>
3
#include <stdarg.h>
4
5
6
//--------------------------------------------------------------
7
// Defines
8
//--------------------------------------------------------------
9
#define  STRING_BUF_SIZE     50   // maximum Grösse vom String
10
11
12
//--------------------------------------------------------------
13
// Globaler String-Puffer
14
//--------------------------------------------------------------
15
char STRING_BUF[STRING_BUF_SIZE];
16
17
18
//--------------------------------------------------------------
19
// Anzahl der Nachkommastellen bei Float
20
//  Faktor ->  100 = 2 Nachkommastellen,  Formatierung -> "%d.%02d"
21
//  Faktor -> 1000 = 3 Nachkommastellen,  Formatierung -> "%d.%03d"
22
//  usw
23
//--------------------------------------------------------------
24
#define  STRING_FLOAT_FAKTOR     1000   // 1000 = 3 Nachkommastellen
25
#define  STRING_FLOAT_FORMAT "%d.%03d"  // Formatierung
26
27
28
//--------------------------------------------------------------
29
// Globale Funktionen
30
//--------------------------------------------------------------
31
void UB_String_FloatToDezStr(float wert);

von Stm M. (stmfresser)


Lesenswert?

Danke.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.