A blog about electronics and programming
Home Electronics How to use STM32 Nucleo serial port

How to use STM32 Nucleo serial port

by Carmine Noviello
39 comments 4.1K views 10 minutes read

As we have seen in the previous tutorial about this new developing board from ST, the STM32 Nucleo provides an integrated ST Link v2.1 interface. ST Link is mainly designed to allow flashing of target MCU trough the mini-USB interface. But, it provides at least another really useful feature: a Virtual COM port. When you install the ST-Link drivers, a new device appears in your hardware devices list: the ST-Link Virtual COM port.

2015-01-24 08_38_11-Device Manager

If you use a Linux PC or a Mac, you'll find a new terminal in the /dev directory. Usually, this device is named something similar to tty.usbmodemXXXX, as shown below.

Schermata 2015-01-24 alle 08.40.43

The serial port is mostly useful for two reasons: if you want to debug your firmware printing messages (not strictly necessary with the ARM architecture, since we can also use ARM semihosting) or if you want to exchange commands and messages between your Nucleo board and your PC (perhaps, using a dedicated application you are building).

In this post I'll show you how to properly configure and use the integrated virtual COM port of STM32 Nucleo board. But, before we start coding, it could be really useful take a look to the hardware. ST provides the full hardware project of the STM32 Nucleo (the board is designed using the Altium Designer CAD, a professional CAD used in the electronics industry, but you are not required to have a so expensive piece of software to use your Nucleo). I'll assume the Nucleo-F401RE model, but it should be really easy to rearrange instructions to properly use your specific Nucleo.

First: pinout

A complex yet flexible MCU like the STM32 provides I/Os that have "overloaded" functionalities.This means that, before we can use a peripheral (in our case, the USART), we need to configure the peripherals associated to corresponding pins. Looking to STM32CubeMX tool, we discover that the STM32F401RETx processor has 3 different USARTs: USART1, USART2 and USART6.

[lightbox full="http://www.carminenoviello.com/wp-content/uploads/2015/01/2015-01-24-08_52_46-STM32CubeMX-uart2.ioc_-STM32F401RETx.png"]2015-01-24 08_52_46-STM32CubeMX uart2.ioc_ STM32F401RETx

[/lightbox]

Now we have to take a look to the Nucleo schematics. As we can see in the following picture, the USART_TX and USART_RX ports are connected to PA2 and PA3 pins. This means that the Nucleo board is configured to use the USART2 peripheral of target MCU.

[lightbox full="http://www.carminenoviello.com/wp-content/uploads/2015/01/stm32-nucleo-usart-pinout.jpg"]stm32-nucleo-usart-pinout[/lightbox]

Ok. We've grabbed all the necessary information related to the hardware needed to start coding.

Second: the code

Before we start configuring the USART2 peripheral, we need a test project. We'll generate an empty project using the GCC ARM Eclipse plug-in, as shown in my series about the GCC toolchain for the STM32 platform. When you generate the test project, you can using the following configuration parameters.

Schermata 2015-01-24 alle 09.17.09If you have followed my previous tutorial about GNU Eclipse plug-in, you already know that the plug-ins generates an incorrect clock configuration for the Nucleo-F4 board. I've shown how to use the STM32CubeMX tool to generate the right clock initialization code. For the sake of simplicity, this is the code you have to put inside the _initialize_hardware.c file.

Next, we have to add a function to configure the USART interface. We call it MX_USART2_UART_Init, as shown below.

The function is really self-explaining. huart2 is an instance of UART_HandleTypeDef descriptor. It's a struct used to configure the UART peripheral. However, this code is still not sufficient to use the UART. We need to configure the hardware part, setting the right pins and initializing the right clocks associated to UART peripheral. This work is done with the following hook function:

Even in this case, the code is really self explaining. First, we need to initialize peripheral clock for PORTA GPIOs. Next, we need to enable the clock associated to UART2 peripheral. Finally, we have to proper configure PIN2 e PIN3 as UART2 TX and UART2 RX.

An important aspect to remark is that we don't need to explicit call this function in the initialization section. This is an hook function automatically called by the HAL_UART_Init() function which we call inside the function MX_USART2_UART_Init().  The right place to call this initialization function is inside the __initialize_hardware() function in the  _initialize_hardware.c file.

Ok. Now we only need to write a simple main() function to test the UART.

The main() is really simple: it simply prints a message on the UART and hangs for ever.

Before we can compile the whole project, we need to do another final operation. By default, the GNU-ARM plugin for Eclipse disables unused STM32 HAL files, in order to speed up compile operation. So, we need to enable the compilation of stm32f4xx_hal_uart.c file.
Go in Project Explorer->system->src->stm32f4-hal and click with mouse right button on the stm32f4xx_hal_uart.c file, as shown in the following picture:

[lightbox full="http://www.carminenoviello.com/wp-content/uploads/2015/02/Schermata-02-2457080-alle-13.25.27.png" title=""]Schermata 02-2457080 alle 13.25.27

[/lightbox]

Click on "Properties" and go to C/C++ Build and uncheck "Exclude from build", as shown below.

[lightbox full="http://www.carminenoviello.com/wp-content/uploads/2015/02/Schermata-02-2457080-alle-14.10.44.png" title=""]Schermata 02-2457080 alle 14.10.44[/lightbox]

Ok. Now we can compile the test project and upload on our Nucleo board using GDB and OpenOCD.

To see messages on the UART you have several options according the Operating System you use. On the Eclipse Marketplace you'll find several terminal emulator plug-ins. TCF is one of these. Another option for Windows OSes is to use putty. On Mac and Linux ckermit is a suitable option.

[lightbox full="http://www.carminenoviello.com/wp-content/uploads/2015/02/Schermata-02-2457080-alle-15.08.19.png" title=""]Schermata 02-2457080 alle 15.08.19[/lightbox]

You can download the whole project from my github repository.

In a next article, I'll show you how to use the others Nucleo UARTs. Stay tuned 😉


You may also like

39 comments

Marius June 9, 2015 - 8:34 pm

I guess there just aren't any tutorials which touches Eclipse IDE, just aren't!.
This is due the inconsistency mess that comes with any Java tools....
I consider I am an experienced engineer (coinscode.com)
and I was struggling entire day to get one simple ST Micro
compiled under Linux and I could not. I gave up. Though, the
tutorial is complete but Eclipse screw it up totally, and screws up
any decent programmer.

Reply
Carmine Noviello June 10, 2015 - 1:34 pm

Hi Marius,
I agree with you: Eclipse can transform every programmer in a serial killer, especially if you have a non so recent PC. I've also successfully setup a complete working toolchain based on a Makefile and a simple text editor like VIM. I'll spend two words about this soon.

Reply
tinkerer August 25, 2016 - 3:03 pm

But there's also Code::Blocks which runs much more smoothly than eclipse - and guess what, it's not Java based 😉
I've read about some people using it for gcc arm embedded work, have not tried embedded dev in c::b myself

Reply
Merelda August 27, 2015 - 6:41 am

Hey, just want to say thanks for the post. Clear explanation and great write-up. I'm actually using Keil uvision but it's still very relevant, thanks

Reply
Merelda August 27, 2015 - 11:29 am

Is it possible for you to add HAL_UART_Receive() function? I tried to look everywhere but can't find any examples on Receiving from Serial monitor/keybaord.. Thanks!

Reply
Kacper October 18, 2015 - 9:47 pm

Hello, thanks for all tips. I'm trying to get UART working for quite some time now and it's driving me nuts I can't do it. I'm using CUBE + IAR and HAL. Any tips why instead of getting normal characters I'm receiving garbage? I'm using HAL_UART_Transmit. What I'm missing?

Reply
Carmine Noviello October 19, 2015 - 6:24 am

Hi,
to give a better help I need to know the type of your Nucleo board. Moreover, past here the clock and UART configuration routines.

Reply
RaulP December 23, 2015 - 5:09 pm

Hi Carmine,
Its a great tutorial I must say. But do you have a an example to interact with the STM32 Nucleo over serial port.I am trying it out using the Serial APIS on windows and can get the data on the STM32 Nucleo (with few glitches).Just wondering if you have a working - clean example for the same.
Eager to hear from your side.!
Rgds,
Rp

Reply
Carmine Noviello December 23, 2015 - 5:45 pm

Hi RaulP,
Take a look to this repository:

https://github.com/cnoviello/mastering-stm32

You should find what you are looking for under the "CH8" examples.

Reply
RaulP December 26, 2015 - 3:49 pm

Hi Carmine,
OK , I followed the instructions from your book and able to create the Eclipse Environment. I am able to build and flash the hello-nucleo image and see the LED in action.
Just wondering is it that simple to use the projects you have uploaded on git.I tried with CH8 chapter for f401re to test the serial port application. But I am getting this error :

make all
Building file: ../system/src/stm32f4xx/stm32f4xx_hal.c
Invoking: Cross ARM C Compiler
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-move-loop-invariants -Wextra -g3 -DDEBUG -DOS_USE_SEMIHOSTING -DTRACE -DOS_USE_TRACE_SEMIHOSTING_DEBUG -DSTM32F401xE -I/Users/cnoviello/STM32Toolchain/mastering-stm32/nucleo-f401RE/include -I/Users/cnoviello/STM32Toolchain/mastering-stm32/nucleo-f401RE/system/include -I/Users/cnoviello/STM32Toolchain/mastering-stm32/nucleo-f401RE/system/include/cmsis -I/Users/cnoviello/STM32Toolchain/mastering-stm32/nucleo-f401RE/system/include/stm32f4xx -I/Users/cnoviello/STM32Toolchain/mastering-stm32/nucleo-f401RE/system/include/cmsis/device -std=gnu11 -MMD -MP -MF"system/src/stm32f4xx/stm32f4xx_hal.d" -MT"system/src/stm32f4xx/stm32f4xx_hal.o" -c -o "system/src/stm32f4xx/stm32f4xx_hal.o" "../system/src/stm32f4xx/stm32f4xx_hal.c"
../system/src/stm32f4xx/stm32f4xx_hal.c:54:27: fatal error: stm32f4xx_hal.h: No such file or directory
compilation terminated.
make: *** [system/src/stm32f4xx/stm32f4xx_hal.o] Error 1
system/src/stm32f4xx/subdir.mk:213: recipe for target 'system/src/stm32f4xx/stm32f4xx_hal.o' failed

Or I may be missing something very minuscule here. While I try to figure it out can you please tell if you have any serial Application running on windows(even a console line will do) which can send a string pattern ( N number of times - different string with different length).

C:\STM32Toolchain\projects\nucleo-f401RE\src\ch8 is the file I am referring to currently to test the serial communication (reception part mostly).

C:\STM32Toolchain\projects\nucleo-f401RE is the project I am referring to .

Thanks and Rgds,
Rp
And yes Merry X-Mas !!

Reply
RaulP December 26, 2015 - 7:35 pm

OK I fixed this one by fixing the Include Paths for GNU C and C++.But I am really looking for a way(a windows application which can send data as I said previously) to STM32 and later can also process it.
Thanks in advance !
Rgds,
Rp

Reply
Carmine Noviello December 31, 2015 - 10:21 am

Hi,
For the Windows application you can take in consideration to create a simple Python script with pyserial module. It would be really easy to do the app you need.

Reply
RaulP January 1, 2016 - 8:18 am

ok thanks for the info /I will try it out.
can it also send the end of line characters at the end of the line read form the text file?

Reply
Carmine Noviello January 1, 2016 - 10:43 am

Yes, for sure. It's just a byte sent over the serial interface.

Reply
tiwag February 23, 2016 - 10:10 pm

thanks, very useful! got it to work faster than feared.
do you have also examples using the interrupt driven uart?

Reply
Carmine Noviello February 24, 2016 - 6:45 am

Take a look to examples of my book:

https://github.com/cnoviello/mastering-stm32

In Chapter 8 examples you'll find also how to UART in interrupt mode.

Reply
DEM May 16, 2016 - 10:47 pm

Hello Carmine. All great posts. Great Job. I have followed these instructions to get this working with my STM32F401RE and could build it. I did veer from the path a but by enabling TIM1 in CubeMX using FreeRTOS as my OS. What I am getting is a TIM6_DAC_IRQn is undeclared in the stm32f4xx_hal_tim_template.c file and TIM6 undeclared in the in the same file.
How can I be able to clear this up so can build the project?

Reply
DEM May 16, 2016 - 10:53 pm

My previous post should have read "...and could not build it." Apologize.

Reply
DEM May 17, 2016 - 2:26 am

I actually Excluded the file above from the project and it build. Not sure if this was the correct course of action.

Reply
Carmine Noviello May 17, 2016 - 6:06 am

Yes, this is the right procedure 😉

Reply
Chandan Mishra May 27, 2016 - 11:33 am

I facing compilation error :

./src/_initialize_hardware.o: In function MX_USART1_UART_Init':
C:\Users\wi2wi\stm4f32xx\test\Debug/../src/_initialize_hardware.c:152: undefined reference to
HAL_UART_Init'

I have check hal_uart.h file properties exclude resource from build

Please help me to solve this error.

Reply
Carmine Noviello May 27, 2016 - 11:37 am

Ensure that the macro HAL_UART_MODULE_ENABLED is uncommented inside the file stm32fxxx_hal_conf.h.

Reply
Tyler June 10, 2016 - 7:13 pm

Hi Carmine,
First I would like to say that your book has been very helpful! Definitely worth the $20. But when I got to chapter 8 and couldn't get the serial communication to work. I used the code from this tutorial (not the one in the book) and compiled it successfully, opened ckermit (I'm using Ubuntu), and realized my device is not showing up in the dev folder shown here: http://pastebin.com/sxyJVJQJ
I tried "set line stlinkv2_5" and "set line /dev/tty" in ckermit and neither one worked. Any help would be great!

Reply
Carmine Noviello June 11, 2016 - 6:08 am

Hi Tyler,
can you post the output from the "dmesg" command? I'm interested to the part when the ST-LINK interface is attached to the USB port. It looks an issue related to drivers.

Reply
Tyler June 13, 2016 - 4:54 am

I am working on a STM32F4 Disco board on Ubuntu with OpenOCD and Eclipse. I have read that I cannot do this via the usb cable connected to CN5 because I do not have a nucleo board. Would it work if I bought a USB to UART or USB to Serial? Would my computer recognize it as a COM device? I am trying to get it to work like the output of this 20 second video: https://www.youtube.com/watch?v=hHdDslVI7O0 I have already changed the nucleo code to fit the disco board by changing the pins and baud rate. I will post a link to the source and the output of "dmesg" tomorrow morning. Thank you for taking the time to help me. It means a lot.

Reply
Carmine Noviello June 13, 2016 - 1:45 pm

Hi Tyler,
Like all ST development boards (Nucleo, Disco, Eval), the STM32F4-Disco has an integrated ST-LINK interface, which also provides a VCP. So, by connecting it to the USB you should be able to send UART message to the PC. It's a matter of drivers.

The CN5 allows you to test USB OTG features, but it's not what you are looking for (it doesn't help having a UART to USB cable).

Reply
Tyler June 13, 2016 - 2:51 pm

I'm confused because I am getting different answers between you and the ST forums: https://goo.gl/B2IKXN This is the output of "dmesg" when just the CN1 cable is connected. When CN1 and CN5 are connected to the computer, all of the LEDs on the board turn off (even when in DFU mode). Regardless of the configuration, I cannot get the device /dev/tty* to appear.

Carmine Noviello June 13, 2016 - 3:00 pm

Ummm, I don't have direct experience with the STM32F4-Discovery board. I thought it has the VCP as the most of ST dev boards, but it seems that this feature is only possibile in the "more recent" STM32F4-DISC1. But it is also required do modify the board, as described here at page 13.

You so need an external UART-to-USB dongle to interface one of the 407VG UARTs.

Tyler June 13, 2016 - 3:39 pm

I will purchase one. Thanks for the help!

Carmine Noviello June 13, 2016 - 3:42 pm

Yes, I think it's the best option. Because the other solution suggested by the user markt on the ST forum requires that you have a quite good knowledge of this platform, and that you are able to configure the USB stack from ST to create a "custom" VCP port. A 5$ UART->USB converter is the best choice in this phase.

Tyler June 13, 2016 - 2:52 pm

I apologize, I did not link the output. This is the output of "dmesg" http://pastebin.com/FuTf7NW4

Reply
Chandan Mishra August 22, 2016 - 1:48 pm

controller : STM32F411RE

I am using USART2 as serial port with interrupt based. I enable NVIC in stmcubemx, its generated code whenever data is transferred from terminal interrupt is coming but uart state is HAL_UART_STATE_READY. Because of that its going to receive function UART_Receive_IT function and came out. Please help solve this issue and also I need guidance how to make uart as a interrupt mode.

Reply
Sumit January 16, 2017 - 10:30 am

Hello,

I have one query. Can we use multiple uart to receive data using STM 32F207 Nucleo 144 board?? If yes do we Need to use multiple bufferes or Need to use timers??

I want to initilaise UART1,2,3 to receive data flowing through communication bus System.

Reply
Carmine Noviello January 16, 2017 - 11:18 pm

Yes, you are free to use as many UARTs as you need. Clearly, the application needs to be designed accordingly. Using multiple buffers is a possible solution (and probably the simplest one), but it depends a lot on the way you arrange your application.

There is no need to use timers, I guess.

Reply
Manikandan March 24, 2017 - 10:53 am

Hi carmine,

I'm using Nucleo F207ZG board in that i tried to make USB_CDC

I attached St in build link with USB Micro B cable (CN1) to ubuntu machine and also connected Micro B cable (CN13) to another USB port of same ubuntu machine but it not showing properly , Ubuntu machine detect only St-link.

In usbd_conf.c I did hpcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;

And Heap size as 4000 and stack size as 2000

Then aslo it's STM Target board not detect , what i want to do ? Is there is problem in USB Cable whic i fixed Micro B usb cable in CN13

And what about jumper JP4 , (I'm using USB as device only so i OFF it )

Reply
Teo Maras September 5, 2017 - 4:39 pm

Hi Carmine,
I'm trying to connect a STM32 board (on which VCOM is used and seen as UART on standard PC), to a Raspberry pi.
Do you know if there is any driver for STM32 VCOM for Raspbian?

Matteo

Reply
Samantha Bowman July 3, 2018 - 5:50 pm

Would this work the same for Nucleo F446RE board or would there be a different process?

Reply
Adición de conectividad Ethernet a un STM32-Nucleo - Electronica April 9, 2019 - 3:29 am

[…] para enviar algunos mensajes en el puerto COM virtual. Puedes encontrar más sobre esto aquí . Antes de que podamos imprimir mensajes en la serie, debemos configurar la interfaz […]

Reply
Rami August 13, 2019 - 5:04 pm

Hello Carmine,

I am using NucleoF401RE I am facing two issues.
1 - When I run the code on my OSX, it works with no problem in polling mode. However, if I run the same code on windows 10, I get garbage output to the terminal. I checked that the Baud rate is matching for both terminal (eclipse) and my code. I have also tried all the possible available Baud rates and same issue.
2- When I follow your example from the book and try to use interrupts, the code gets stuck and I dont receive any output. I can't figure out how to make interrupts work.
Thanks for the help.

Reply

Leave a Reply to Carmine Noviello Cancel Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.