1

I use this code for retarget printf(), but it does not work

#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

PUTCHAR_PROTOTYPE
{
    /* Place your implementation of fputc here */
      /* e.g. write a character to the LCD */
    lcd_Data_Write((u8)ch);

      return ch;
}

I use STM32F103RBT6

compiler : GCC with emBitz editor

Bence Kaulics
  • 7,066
  • 7
  • 33
  • 63
Delay
  • 93
  • 3
  • 9
  • Possibly a duplication of http://stackoverflow.com/questions/39664071/how-to-make-printf-work-on-stm32f103/ – SamR Oct 03 '16 at 20:05
  • Might be useful: http://electronics.stackexchange.com/questions/206113/how-do-i-use-the-printf-function-on-stm32 – Bence Kaulics Jan 12 '17 at 18:24

4 Answers4

2

Try hijacking the _write function like so:

#define STDOUT_FILENO   1
#define STDERR_FILENO   2

int _write(int file, char *ptr, int len)
{
    switch (file)
    {
    case STDOUT_FILENO: /*stdout*/
        // Send the string somewhere
        break;
    case STDERR_FILENO: /* stderr */
        // Send the string somewhere
        break;
    default:
        return -1;
    }
    return len;
}
MathiasE
  • 467
  • 3
  • 10
  • I'm using this method on an STM32F072. Details here. http://electronics.stackexchange.com/questions/206113/how-do-i-use-the-printf-function-on-stm32/279945#279945 – cp.engr Jan 13 '17 at 05:36
1

As an alternative, you could write your own printf() function using, Variable Argument Functions (va_list).

With va_list a custom print function looks like the following:

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

void vprint(const char *fmt, va_list argp)
{
    char string[200];
    if(0 < vsprintf(string,fmt,argp)) // build string
    {
        HAL_UART_Transmit(&huart1, (uint8_t*)string, strlen(string), 0xffffff); // send message via UART
    }
}

void my_printf(const char *fmt, ...) // custom printf() function
{
    va_list argp;
    va_start(argp, fmt);
    vprint(target, fmt, argp);
    va_end(argp);
}

Usage example:

uint16_t year = 2016;
uint8_t month = 10;
uint8_t day   = 02;
char* date = "date";

// "Today's date: 2015-12-18"
my_printf("Today's %s: %d-%d-%d\r\n", date, year, month, day);

Note that while this solution gives you convenient function to use, it is slower than sending raw data or using even sprintf(). I have used this solution both on AVR and on STM32 microcontrollers.

You could further modify the vprint like this, where periphery_t is a simple enum type:

void vprint(periphery_t target, const char *fmt, va_list argp)
{
    char string[200];
    if(0 < vsprintf(string,fmt,argp))
    {
        switch(target)
        {
            case PC: PC_send_str(string);
                break;
            case GSM: GSM_send_str(string);
                break;
            case LCD: LCD_print_str(string);
                break;
            default: LCD_print_str(string);
                break;
        }
    }
}
Bence Kaulics
  • 7,066
  • 7
  • 33
  • 63
0

Tank you Bence Kaulics

I use tinyprintf library and it worked quite well : github link

Delay
  • 93
  • 3
  • 9
0

just make sure to add the following in the init code:

// Turn off buffers, so I/O occurs immediately
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);