HAL Library 07- USART for STM32Fxxx

Here it is. UART library for HAL based libraries. If you don’t know, how UART work on STM32Fxxx devices, then you might take a look at my first library, where I also explained how to used it.

This library works successfully on F4 and F7 based devices for now. I will add support for F0 too as soon as possible.


Read more about new HAL libraries


  • Supports up to 8 UART peripherals at a time
  • Interrupt driven RX
  • Support for different UART omdes
  • Support for receiveing string
  • Support for sending string/character/array
  • Supports multiple predefined GPIO pins for specific UART or custom based pin initialization


  • HAL
  • TM
    • STM32Fxxx HAL
    • defines.h
    • GPIO
    • BUFFER


Below are possible USART pins. You select them on USART initialization.

Pins pack 1 Pins pack 2 Pins pack 3
USART3 PB10 PB11 PC10 PC11 PD8 PD9

Functions and enumerations

Example 1

Example 2

Example 3

Projects are available on Github, download all libraries below.

TM STM32 Libraries

STM32 libraries based on STM32Fxxx HAL drivers.


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!
  • Pingback: All STM32 HAL libraries - STM32F4 Discovery()

  • batman Simon

    Hi Tilen, I using custom pin tx:PD13, rx:PD14 – baurate:9600 . During I init

    /* TX pin = PD13 */

    TM_GPIO_InitAlternate(GPIOD, GPIO_PIN_13, TM_GPIO_OType_PP, TM_GPIO_PuPd_UP, TM_GPIO_Speed_Medium, AlternateFunction);

    /* RX pin = PD14 */

    TM_GPIO_InitAlternate(GPIOD, GPIO_PIN_14, TM_GPIO_OType_PP, TM_GPIO_PuPd_UP, TM_GPIO_Speed_Medium, AlternateFunction);

    —>>> But USART Not Activity . Error ???

    • Hi, which stm32 series, which usart?

      • batman Simon

        Hi. I using :
        TM_USART_Init(USART2, TM_USART_PinsPack_Custom, 9600);

        • Will ask again.
          Which STM32 series?
          Is PLL clock set correct? If not, it won’t work!

          • batman Simon

            NO. I not set PLL clock . In example i see you not set. So how set PLL clook ? Thanks you.

          • Still don’t know which STm32 series you have!

          • batman Simon

            I using STM32f407VET.

  • lothes

    Hey, first off thanks a lot for the great work, I tried using this library with an STM32F0 along with the gps library, gps library worked with STM32F4 using HAL drivers but on F0 the GPS_Data doesn’t get updated.

    • Hi,

      so as you already figured, something is problem with USART.
      I will have to take a look on what is going on here before i give you any info.

      Does USART works OK, if you use FTDI on these pins and you communicate?
      Clock has sense here for STM so if you failed, baudrate will also fail.

      • lothes

        Hey, it does send yes even on USART 3 but it seems like an issue with receiving data/buffer, at first the code didn’t compile for the stmf0 , i changed the Alternate function to AF1 and then AF4 (instead of AF7) for USART , also IRQ is irq_3_4, it compliled but still data isn’t received correctly. Thanks for the fast reply!

        • I see now.
          I don’t have implemented IRQ handlers for STM32F0 so data is not received everywhere.

          • lothes

            Any pointers to how I can add them?

          • You need functions which are done for your USART interrupt handler.
            Functions are described in startup files for your USART.

          • lothes

            Thanks a lot, I’ll look into it!

          • lothes

            Hey, by startup file for USART do you mean the startup_stm32fxxxx.s file?
            Would changing these help ? http://pastebin.com/ng7Puyrr

          • Yes, that file.
            Why? No.

          • lothes

            Honestly I couldn’t find anthg to change in that file in order to add the irq handlers, I have considered changing the reading function to read from the RDR register, but I am not sure if tht would solve the problem. Thanks for the help anyways!

          • For example.
            F4 and F7 series for USART1 USART1_IRQHandler function name for handling interrupts.
            On F0, USART1 may have USART1_2_IRQHandler() function. This function shares USART1 and USART2 interrupts. This is what you have to check!

          • lothes

            Hey, so I’ve given up but then I was able to activate the irq handler for usart 3 , now data appears in the RDR register but looks like it’s not inserted into buffer, I’ve narrowed down the issue to this (ive made a couple of changes to the irq handler).


            Thanks a lot for the help!

          • lothes

            It just worked! changed USART_FLAG_RXNE to USART_ISR_RXNE.

  • Tim Kostka

    I think you need to initialize UARTHandle.Init.OverSampling within TM_USART_Init to a valid value. I couldn’t figure out why this library wasn’t working for me, but it was blocking at the following statement within the HAL library (v1.4.1):


    Added the following line which fixed it:

    UARTHandle.Init.OverSampling = UART_OVERSAMPLING_8;

    (Thanks for the libraries, they are hugely helpful!)

    • Thabks for reporting this.
      I have 1.8.0 version which works ok.

      Will fix it.

  • John Doe

    Hi, Stupid question here? What is a pinspack? I am using the demo with UART6. Do not get any output.How do I select pinspack 1 vs pinspack2 ?

    • Pinspack is MY (My, Tilens) system of package of pins used for initializations.
      So, if you take a look at pins table, find USART6 and find your pins. Then check which pinspack is used and use it in your settings.

      • John Doe

        OK, I see now. Thanks. I think I have the correct config then (stm32f429i-disco board). Connecting to a
        FT232RL FTDI USB To TTL Serial Converter, but on input or output displayed from putty. I have correct port speed, etc. Any suggestions? The FTDI boad uses either 3.3 or 5.v. I have it jumpered for 3.3 v.

  • Jeremy Vance

    First off, great library! I have one need though that I cannot figure out. I need to change the baudrate on the com port. From what I can tell, the only way to change the baud is by calling the init function again which, for me, locks up (at call to HAL_UART_Init(&UARTHandle);). I don’t see a deinit function so how do I change the baud rate? Thanks!

    • Hi, I would like to know, where it hangs? Go to debig please and test.

      • Jeremy Vance

        I rebuilt the firmware and couldn’t get it to hang on Init again and it was changing baudrates but I’ve found that it wants to hang or rather loop on USART1_IRQHandler function.
        The problem occurs after I start receiving data on a different baud rate than originally set to. I start at 57600, try communication which fails, so I start over at 1200, 2400, 4800 which gives me data. However, I get the first expected character correctly, then the IRQ just loops. My USART1 SR Register isn’t showing data (RXNE flag) any more but it is looping because it is greater than 0. The TXE flag and TC flag are set. Should these be ignored by the IRQ and reset in clear all flags?

        • After I started with ESP library, I noticed that too. So I tried to fix it and for now it works, but not sure if it works totally OK.

          Right now, I’ve uploaded new version to website (not yet on github) which at least should fix that problems. Download entire pack of libs from this post at the end and test 🙂

          • Jeremy Vance

            Thanks for the new library. That seemed to fix my problem with multiple baudrates and IRQ. On copying your library over, I remembered a change I had to make that I wanted to run past you. In STM32fxxx_hal.h I moved defines.h to the top of the file because I define which microcontroller in defines. With it towards the end of the file I would always get the “No STM family selected…” error. Am I defining the family in the wrong place? Just thought I’d bring it up in case there were others with the same problem.

            Thanks again, I’ll keep testing and let you know if any issues arise with the new libraries. My program is very UART heavy.

          • Nice to hear it works. This is actually great idea. Will add that. It shouldnt change anything at all.

            Well, i make define in IDE where compiler preprocessor defines can be used.

  • Magnus

    Thanks a lot for all the sw you have done for the STM32!

    I trying to compile Example 2
    from the “HAL Library 07- USART for STM32Fxxx”.

    When I add the line #include “tm_stm32_usart.h” and compile, I got this error:

    undeclared (first use in this function) STM32F4-Discovery line
    525, external location: C:UsersMagnusSTM32CubeHALtm_stm32_usart.h C/C++ Problem

    Can you help me out with a solution?

    I am using OPEN
    STM32 IDE SW4stm32.


    • Have you read more about hal drivers at mentioned in begin of post?

      • Magnus

        Hi Majerle.
        Yes, red your first UART library. Do you understand why the compiler says that ‘USART_FLAG_TXE’undeclared ?
        Best regards

        • I do understand why compiler says that. Because it is not declared.

          But did you read what you have to do in defines and what type you have define before you get to work everything?

          It is a link in this post!

          • Magnus

            I have red what I need to do in defines and I do not understand why the compilation do not pass.

            When i add #include “stm32f4xx_hal_usart.h”, to the included file tm_stm32_usart.h
            I get rid of the ‘USART_FLAG_TXE’undeclared. That is good, but an other compilation error is now displayed:

            “undefined reference to `TM_RCC_InitSystem’ main.c /STM32F4-Discovery/Example/User line 117 C/C++ Problem”.

            Can you help me out regading this issue?


          • As error says again, TM_RCC_… is not in your project.

            TM_RCC means RCC lib from me. Download it and use it.

          • Magnus

            Hi Majerle,

            I have been trying a lot to make the HAL USART Example 2 work, without success.

            Can you help me out with your “Example 2” as a complete project for ST’s “OPENSTM32 IDE SW4stm32”?

            Best regards

          • Hi,

            What is not working?

          • Magnus

            I am trying to compile the Example 2 usart HAL.
            I have got a compilation error:

            fatal error: board.h: No such file or directory STM32F4-Discovery line 31, external location: C:….stm32f4xx_rcc.h

            I do not have any “board.h”.


          • Looks like you are compiling sonething wrong. File you are missing has nothing to do with usart.

          • Magnus

            Are you using CooCox IDE?
            Can you export the complete “USART HAL Example 2” project?

            Best regards

          • I’m not using it anymore.
            So, you can figure it yourself or contact me private with detailed info, maybe teamviewer if needed.

          • Magnus


            Can you help me out via Teamviewer at my current ST’s “OPENSTM32 IDE SW4stm32” TM HAL USART project?


          • Like I said, contact me private if needed for teamviewer.

  • zitouni

    hi Tilen
    how I can transfer this function

    char ReceiveData;

    void usart_read()

    {while(USART_GetFlagStatus(USART2, USART_FLAG_RXNE)==RESET)



    } in function to read a string

  • Pingback: HAL Library 32- DMA extension for USART on STM32Fxxx - STM32F4 Discovery()

  • Alessandro

    Hello Tilen.
    I wanted to first of all congratulate you for your wonderful work, easy to use and well done.

    Allow me to alert you a potential problem in TM_BUFFER_Find () function used in a UART context.

    The problem is emerged carrying a continuous polling of the modem signal (the answer is almost always the same).
    I noticed that the TM_USART_FindString () identified the search string
    and i went immediately to download the buffer through TM_USART_Getc ().

    Very rarely, however, I noticed that remained other bytes in the buffer.
    That was because ‘TM_USART_FindString () gave a positive result but the modem had not sent all the bytes.

    After hours of testing I think I identified the problem.

    In summary: the TM_BUFFER_Find (), when it gets to the correct first
    character of the sequence to be searched, enter a loop that does not control the exhaustion of bytes consistent.

    If by luck found the correct sequence, exploiting the old bytes, back successfully.

    it follows that the caller, believed to have downloaded all the bytes
    and on the call, pointer to circular buffer (out ), falls behind.

    I solved the problem with very few controls.

    If you are interested, I post my changes.

    Thanks again for your attention and especially for your work!

    int32_t TM_BUFFER_Find(TM_BUFFER_t* Buffer, uint8_t* Data, uint32_t Size) {

    uint32_t Num, Out, i, retval = 0;
    uint8_t found = 0;

    /* Check buffer structure and number of elements in buffer */
    if (Buffer == NULL || (Num = TM_BUFFER_GetFull(Buffer)) Out;

    /* Go through input elements in buffer */
    while (Num > 0) {
    /* Check output overflow */
    if (Out >= Buffer->Size) {
    Out = 0;

    /* Check if current element in buffer matches first element in data array */
    if ((uint8_t)Buffer->Buffer[Out] == (uint8_t)Data[0]) {
    found = 1;

    /* Set new variables */

    /* We have found first element */
    if (found) {

    if(Size == 1)
    //looking for a single character and found this
    return retval;

    if(Num == 0)
    //I found the initial character but there are no other
    return -1;

    /* First character found */
    /* Check others */
    i = 1;
    while ((i 0)) {

    //loop while i = Buffer->Size) {
    Out = 0;

    /* Check if current character in buffer matches character in string */
    if ((uint8_t)Buffer->Buffer[Out] != (uint8_t)Data[i]) {
    retval += i – 1;

    //I found correct characters but a wrong one arrives -> Variable reinit
    found = 0;

    /* Set new variables */

    /* We have found data sequence in buffer */
    if (i == Size) {
    return retval;

    /* Data sequence is not in buffer */
    return -1;

    • First of all, thanks for this catch.

      I don’t understand this: “The problem is emerged carrying a continuous polling of the modem signal (the answer is almost always the same).”

      I would like to see tests or cases where this happens.

      You did not read “read before comment” section saying “Do NOT post any code here. Use Pastebin,”

      In your case, I suggest you use Github to send me pull request. I will be able to exactly identify the code change.

      • Alessandro

        Sorry Tilen,

        It’s my fault.
        I didn’t read. Sorry.

        Regard to the phrase “The problem is Emerged carrying a continuous
        polling of the modem signal (the answer is almost always the same).”, It
        was just to make it clear that the phenomenon ‘was more’ easy to find
        ’cause the device responds almost totally with the same sequence of characters.

        Really sorry, but I have not time to prove you now….

        I can only give you cases writing here fast.

        If you believe my words credible, then watch your function TM_BUFFER_Find():

        1) You have a device that always responds with r n r n O K r n
        Suppose the TM_BUFFER_GetFull () returns 6 (the device has not transmitted all characters).
        What’s happen if from Buffer->In there is an old sequence
        r n? In my opinion function will be back successfully, despite the
        TM_BUFFER_GetFull () told us that we have received 6 characters and
        not 8.
        My advice is cycling checking I, Size but also Num.

        2) What happens if TM_BUFFER_GetFull () returns 1, and the character is the right to start the sequence to be controlled?
        I think goes on in cycling for Size characters checking an old buffer.

        3) I’m not sure this is a real problem but I submit:
        What happens if you find the correct first character of the sequence
        (variable found = 1) and then can not find other correct characters on the sequence?
        I do not understand if we can have a problem not resetting to 0 the variable found.

        Thank you so much for the attention.
        I hope my English is understandable 😉

  • Bernhard

    Hi Tilen,
    first of all thank you for sharing your work with the community. I have a small problem with your code and I do not see the solution to it. I use a STM32F415 on a own board and in principle USART lib is working except for the inline function “TM_USART_Putc”. When using it (I also tried it to use as a non-inline function) the core runs into an HARDFAULT (Busfault, PRECISERR) after the last character. So when I try to use
    “printf(“Hellon”);” (for sure I used your recommendation for STDIO with your lib).
    The code stucks, but in the terminal programm I can see that the code sends really “Hello”. But after the “o” it crashes. By the way to use n or not doesn’t matter.
    My questions is: Did you already had this problem? Do you have any ideas, what to try?
    By the way “TM_USART_Puts” works fine.

    (I’m using Keil uVsion in its latest version with the KEIL ARM compiler; the code uses KEIL RTX).
    Thanks in advance

    • I must say I have to review code. But BusFaulf, I never got that error.

      • Bernhard

        Thank you for your answer. I was afraid of this, but I cannot exclude that something with the rest of my code is wrong. I will further try it (maybe with a minimum code example, and if I find a solution I will reply here.

  • Charis Faridchie

    is it this library can combined with project generated by stm cube???

  • Tmoc

    I tried to use usart 3 with PD9 as TX and PD8 as RX using the custom pin option, configured using the same logic as example 2 and didn’t work, is this possible ?

    • Did you check if PD9 can be TX and opposite?

      • Tmoc

        Thanks for fast reply, I take a look now on STM32F4 user manual and PD9 can’t be used as TX.
        Now I will try to invert the pin on my ESP8266, if it’s possible.