Use printf to output stream on STM32F4

It would be nice, if you can simply just use printf to direct output strings to USART, LCD, etc. With ARM C, you are able to do this. You just need to implement some things and you are ready to work.

New STDIO library is available here.

To enable printf functionality, first you need to create a new __FILE struct. This struct is then called with FILE struct. It can have only one dummy parameter, but it has to be created, because you need pointer to this structure if you want to output characters to stream. If you need any control for this, you can create your own. I created my own below:

After that, we have to create a variable with FILE struct:

Variable name __stdout is important. You can not use different name, otherwise printf will not work. Last thing we need to create is a function, that will be automatically called from printf and will actually print your charater by character to stream. Function has fixed name and can not be changed.

You are ready to use printf function. Below is simple example, that will output data to USART1 with printf using my USART library.


You will need my USART library for this, download below.

TM STM32F4 USART Library

USART library for all USART peripherals


Owner of this site. Also electronic enthusiasts, web developer, 3D printer fan, handball player and more. Big fan of STM32F4 devices. In anticipation of the new Discovery board for STM32F7 lines.

You may also like...

Read before commenting!

Before you make a new comment, make sure you agree with things listed below:

  • - Read post to make sure if it is already posted what you are asking for,
  • - Make sure you have the latest version of libraries used in your project,
  • - Make a clean and grammatically correct written message,
  • - Report as many details as possible, including what have you done so far,
  • - Do NOT post any code here. Use Pastebin,
  • - Do NOT post any error codes here. Use Pastebin,
  • - Specify STM32Fxxx family and used Discovery/EVAL/Nucleo or custom made board,
  • - Make sure your clock is set correct for PLL,
  • - If you are using my HAL drivers, please check this post how to start.
Comment will be deleted on breaking these rules without notification!
  • phivu

    Hi. I have just follow you guide to program for my applications. It’s very useful for me. I’m doing one project that using external interrupts of PA8 and PA9 for reading pulses. However, It does not show me the value of pulses when I use printf function although I followed your code already. Please help me to fix my program and tell me what I am wrong. This is the address of my code

    • HI. Thanks for posting.

      According to the project you send to me, I would say, that problem is, that you don’t have initialized which pins you will use for USART2. I also enable clock for USART2.

      Didn’t tested this code, because I don’t have hardware here, but you can try this main.c
      Pins for USART2 are: TX = PA2. RX = PA3

      • phivu

        Dear Sir,
        Many thanks from your help very much. My code can run now already. I really highly appriciate your help and your website.
        Best Regards,
        Phi Vu.

        • Isaac Kim

          Hi, first thank you for the help full information and your library. Yet, I can’t build my code because of an error that says : defines.h file doesn’t exist. if it is avaliable to share your defines.h file , please mail me. thank you.

  • Vimukthi Pathirana

    hello, i’m trying to print the value from 3 hall sensors. from that value i’l later get the speed. can u look at my code? problem is USART always print zero when i rotate the motor. i cannot figure out the problem.

    #include “stm32f4xx.h”
    #include “stm32f4xx_rcc.h”
    #include “stm32f4xx_gpio.h”
    #include “stm32f4xx_tim.h”
    #include “stm32f4xx_exti.h”
    #include “tm_stm32f4_delay.h”
    #include “tm_stm32f4_usart.h”
    #include “math.h”

    void configHallSensorTimer(void) {

    TIM_ICInitTypeDef TIM_ICInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    // enable port pins for hall inputs
    RCC_APB2PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

    // timer base configuration
    // 126 => 3,5s till overflow ; 285,714kHz TimerClock [36MHz/Prescaler]

    TIM_TimeBaseStructure.TIM_Prescaler = 126;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period = 65535;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

    // enable hall sensor
    // T1F_ED will be connected to HallSensoren Imputs
    // TIM4_CH1,TIM4_CH2,TIM4_CH3

    TIM_SelectHallSensor(TIM4, ENABLE);

    // HallSensor event is delivered with singnal TI1F_ED
    // (this is XOR of the three hall sensor lines)
    // Signal TI1F_ED: falling and rising ddge of the inputs is used

    TIM_SelectInputTrigger(TIM4, TIM_TS_TI1F_ED);

    // On every TI1F_ED event the counter is resetted and update is tiggered

    TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);

    // Channel 1 in input capture mode
    // on every TCR edge (build from TI1F_ED which is a HallSensor edge)
    // the timervalue is copied into ccr register and a CCR1 Interrupt
    // TIM_IT_CC1 is fired

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

    // listen to T1, the HallSensorEvent

    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_TRC;

    // Div:1, every edge

    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

    // noise filter: 1111 => 72000kHz / factor (==1) / 32 / 8 -> 281kHz
    // input noise filter (reference manual page 322)

    TIM_ICInitStructure.TIM_ICFilter = 0xF;
    TIM_ICInit(TIM4, &TIM_ICInitStructure);

    // channel 2 can be use for commution delay between hallsensor edge
    // and switching the FET into the next step. if this delay time is
    // over the channel 2 generates the commutation signal to the motor timer

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_Pulse = 1; // 1 is no delay; 2000 = 7ms
    TIM_OC2Init(TIM4, &TIM_OCInitStructure);

    // clear interrupt flag

    TIM_ClearFlag(TIM4, TIM_FLAG_CC2);

    //TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
    // TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_OC1);
    // timer2 output compate signal is connected to TRIGO

    TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_OC2Ref);

    // Enable channel 2 compate interrupt request
    // TIM_IT_CC1 | TIM_IT_CC2


    // we use preemption interrupts here, BLDC Bridge switching and
    // Hall has highest priority

    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    // ——————-
    // HallSensor is now configured

    TIM_Cmd(TIM4, ENABLE);

    int main()
    int possition;
    char str[120];
    uint8_t sensor = 0;


    /* Initialize USART, TX: PB6 */
    TM_USART_Init(USART1, TM_USART_PinsPack_2, 9600);

    /* Display message to user */
    TM_USART_Puts(USART1, “Hall sensor is ready to use!n”);

    /* Sensor K */
    sensor = 1;

    /* Every 500ms */
    if (TM_DELAY_Time() >= 500) {
    /* Reset time */

    if (sensor) {
    possition = TIM_GetCounter(TIM4);

    sprintf(str, “Possitionn- %drn”, possition);

    TM_USART_Puts(USART1, str);


  • Julian da Cunha

    Hello I dave done everything as you discribed in your tutorial but I always get the error below, when i try to debug. I even included the “tm_stm32f4_gpio.h” library wich wasnt mentioned in the tutorial. Could you pls help me?

    c:/arm/arm-2011.09/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/armv7e-m/fpulibg.a(lib_a-readr.o): In function _read_r':

    readr.c:(.text._read_r+0x10): undefined reference to _read’

    collect2.exe: error: ld returned 1 exit status

    cs-make: *** [Workshop.elf] Error 1

  • Pingback: All STM32F4 tutorials - STM32F4 Discovery()

  • Anton Khrapov

    Hi Majerle,
    I’m using IAR and it gives me multiple compile errors: Error[Pe020]: identifier “FILE” is undefined
    Do you know why that could happen? I did not forget to include stdio.h.

    • Yeah I know that. IAR compiler does not have this feature done by that way like GCC and MDK-ARM have.

      • Anton Khrapov

        That’s a shame. Thanks.

        • Well, to implement print in IAR, everything you need to do, is to create a function for printf function which will be called. Its structure is as follow:

          int __io_putchar(int ch) {
          /* Send char here */

          At least I think it should work that way.

  • Saman

    Hello Majerle
    I used printf() for usart in the way you described and it was very useful, thank you
    now I want to use scanf for getting character beside printf which you described and i want to use it in same source file.

    how should i do that?
    should i write another structure with different name? or that one is enough and i should use another variable of stdin instead of stdout?

  • Pingback: How to use scanf with USART - STM32F4 Discovery()

  • Jorge Del Aguila

    Hello Tilen!

    This is my first time with keil uVision. I have copied your code and included the correspondant libraries. I have compiled the code and loaded it to board. But when I debbug I check the USART #1, USART #2, USART #3 and Debbug (printf) viewer and nothing is displayed in any of them.

    PD. I’m using the template project you provide on your web site.

    Any idea on what could be the problem?


    • This example has nothing to do with built in keil viewers. For keil debug view, check swo output library on site.

      Printf in this example only transfers formatted string to output it where you want. In example, usart output is used. To see data, you need usb to aurt converter and then open com port.

      • Jorge Del Aguila

        I suspected it. I tryied the other and it’s working perfectly.


  • Chan Kim

    I added tm_stm32fusart code to the project but when I build it, it compains I don’t have misc.h which tm_stm32f_usart.h includes. Where can I get misc.h ?

    • Standard periph drivers.

      • Chan Kim

        Hi, I’ new to this, I can see the misc.h files under C;Keil_v5

        how can I add these include path to the uvision? (sorry for this basic questions)
        I’m testing STM32F401RE board.

        • WolfSSL has nothing with this.
          Download drivers from and add them to proj.

          • Chan Kim

            Hi, I included std periph library and get this many re-defintion warning. what’s wrong? The first one here.. Can I use your code with HAL drivers?

            C:Keil_v5STM32F4xx_DSP_StdPeriph_Lib_V1.6.0LibrariesSTM32F4xx_StdPeriph_Driverincmisc.h(123): warning: #47-D: incompatible redefinition of macro “IS_NVIC_PRIORITY_GROUP” (declared at line 343 of “C:Keil_v5STM32Cube_FW_F4_V1.9.0DriversSTM32F4xx_HAL_DriverIncstm32f4xx_hal_cortex.h”)

          • Why you use STD drivers and HAL drivers at the same time? You can’t do that.

          • Chan Kim

            Oh, I see thanks! I started with a template I took from STM32cubeF4xx which contained many hal drivers. Where is your template somebody mentioned? Thanks.

  • Hassine

    Please i need some library that can i used in voice recognition and how we record the sound by the stm32f4 thanks

  • ZenMaster

    There is a “Software Component” in Keil which allows retargeting. Can you please make a post on how to use it. Thanks in advance

    • With a little thinking, you would already found it 😉 SWO output!

      • ZenMaster

        Thanks for your reply. But it turned out that the problem was the USB port I used. When I changed it, printf worked.


    I am using the above procedure to check the output of USART1 ,using printf command,I have followed the above procedure to direct the output to stdout ,but i didnt see anything on the USART1 terminal and Debug(printf) in keil.They are blank but program is running

    I have written printf(“nATn”);

    // USART1 screen and Debug(printf) screen are blank.

    I am unable to find out the problem with my code.
    Thanks in Advance.

    • For Keil debug display, you need SWO output. Check my SWO library for that. For printf implementation, you have to enable fputc function which will send your string where you want it.


        I have already called the fputc function

        struct __FILE


        int dummy;


        FILE __stdout;

        int fputc(int ch,FILE *f)



        return ch;

        What else apart from this ?

        • Init uart firstand open in terminal your usb uart converter.

  • Peter Mather


    I’ve just tried this under System Workbench and it compiles and runs OK but just ignores the printf. I don’t get any output even though the statement appears to execute and TM_USART_Putc work fine (HAL version)

    Any ideas appreciated

    • For gcc it is different than in armcc. Technicall each compiler has its own.

      Im glad it worked.

  • Bob

    Hi Majerle,

    I am using the STM32F401-RE Nucleo board and followed this code and managed to get some output. I am trying to incorporate this code with your “25-STM32F429_AM2301” code. However, I appear to be printing garbage (please see:

    When I did it separately, it managed to work fine. Is there something wrong with my clock configuration? This board does not have an LCD display to show the temperature and humidity settings. I am using a baud rate of 115200, 1 odd bit, no parity and no flow control.

    Can you please help?

    • Page not found. I believe you failed with clock configuration.
      First try if TM_USART_Putc (if you use my USART lib) works ok. If it does not, check clock setup.

      • Bob

        After taking a closer look, I messed up somewhere in my clock setup. Thanks a lot!