Nucleo F401RE Ports Alternate Functions and sending numbers over UART

It is time to use some alternate functions on ports pins. For this example we will use alternate function of PORTA.2 and PORTA.3 to serve as RX/TX of USART2.

We start new project for Nucleo F401RE in CubeMX:

Now we need to configure USART2:

On the left side select Asynchronous from the drop-down menu of USART2 (marked red).

In the middle you will notice change of color of PINA.2 and PINA.3 (marked green).

Now let’s generate project and open it in SW4STM32.

There is not much of a code added for USART:

  • command to initialize USART2:

  • and the initialization code itself:

Also there is initialization of ports and pins:

But wait… there is no alternate function selection here or any mention of pins PINA.2 and PINA.3… This is done in function: HAL_UART_MspInit(UART_HandleTypeDef* huart) inside stm32f4xx_hal_msp.c.

To check if alternate bits really are set, we need to debug our program and check values of register in I/O Registers window.

First I will add a small delay to set breakpoint at:

and set breakpoint (right click on the scroll bar left from line numbers, where you want to add breakpoint and select Toggle breakpoint):

this will add little blue circle at the breakpoint (circled in red):

Now we need to start the debug, we do this by clicking “little green bug” in toolbar (marked red here):

This opens so called Debug perspective in our SW4STM32. You should see something like picture below. If you clicked something and windows changed, don’t panic, just go to: Window -> Perspective -> Reset Perspective… and all will be reset to default view.

Now click on “play” marked green on the screenshot above and program will start and pause at breakpoint. Now double click on I/O Registers and it will open the registers windows full-screen.

Now click through menu to: GPIO -> GPIOA and expand AFRL and double click on it so that it fetches values from microcontroller:

Here you can see values for AFRL which shows that AFRL2 and AFRL3 have values of 0x7.

Now if you check alternate functions of PORTA pins you can see that these mean that pins’ PINA.2 and PINA.3 alternate functions are set as USART RX/TX:

Now that we checked that everything is set, we need to send some data over UART.

We already have serial communication configured. We only need to add a few commands for sending data. HAL command for this is HAL_UART_Transmit.

This two commands will send “Hello world!” over uart and also send “new line” command. We do this every 5 seconds.

Now that this works we can do second part of this tutorial -> send unsigned  long number over UART. One thing we need to understand is that if we send for example number 5 over uart it will not send number 5, it will send number 53 which is ascii representation of number 5 (see table below). Everything we send over uart gets transformed this way.

All serial communication we will be using uses 8bit numbers which means that we cannot just send unsigned long over uart, but we need to somehow change it to numbers and send ecah number separately over uart. First we need to determine maximum length of string which represents the biggest unsigned long number and that number is 2^32 – 1 = 4,294,967,295. Here we can see that we need to send 10 numbers for maximum value. There are two ways to change number to ascii string, one is using atoi standard C function and the second is to just write some function which will do this.

I must say that I am not sure why but original function from C doesn’t work ok for me, depending on level of optimiztion in SW4STM32 I get different results. My function works for what I need it, but as my friend TILZ0R from STM32F4 says, each function must be robust and I am not sure if mine is robust enough. Enough talking, let’s start coding!

Here is my test program for sending unsigned long over uart:

first we need a couple of variables:

we also need to define our function:

we also need function not just it’s definition:

we also need to tell our compiler to include standard C library:

and finally we use our nice function together with itoa function:

Here is result of my test, yours might be different:

First line is just to show that next line uses function itoa.

Second line is result of transfering number with itoa function (if someone knows what is the problem, please let me know).

Third line says that next two lines use my function (GS_TX_long) and following two lines show values from GPIOA->AFRLH and GPIOA-AFRL.

This concludes this tutorial. Thank you for visiting my site!