How to Receive Data with the UART Communication Protocol with an STM32F446 Microcontroller Board in C

Nucleo STM32F446 board



In this article, we explain how to receive data with the UART communication protocol with an STM32F446 microcontroller board in C.

UART stands for universal asynchronous receiver transmitter, and it is often used to transmit or receive data between a microcontroller and various components.

UART, in its most basic form, only needs 2 pin connections: Tx (for transmission) and Rx (for receiving).

Some pins on the STM32 board are completely dedicated UART pins. Other pins are USART pins, which are UART pins but with the additional capability of being synchronous (in addition to asynchronous). So USART pins have dual capabilities in that they can be run synchronously (with a clock) or asynchronously (without a clock).

If running asynchronously, the transmitting device (such as the STM32 microcontroller) and the receiving device must have the same baud rate (for uniform communication). If they don't have the same baud rate, the data will be corrupted.

UART is best used for short distances.

In this example, we are going to use one of the USART pins in order to implement UART communication.

We will use the UART2_TX and UART2_RX pins, which are realized by pins PA2 and PA3 in alternate function modes.

Below is the alternate function mapping of the GPIO Port A of the STM32F446RE microcontroller.


Alternate function mapping of the GPIO Port A of the STM32F446 microcontroller board


So you can see that if we put pins PA2 and PA3 in alternate function mode 7 (AF7), these pins will act as USART2_TX and USART2_RX.

If you look below these pins, you will see that pin PA4 can act as USART2_CK. However, in our circuit, we don't use this pin because we are using the USART2 pins in UART communication mode, which doesn't require a clock signal to communicate with the other device. If we were using the pin in USART mode, this CK pin would have to be configured and connected to the other device, so that communication could be established synchronously. However, in UART mode, a clock isn't used to establish synchronous communication. All that is needed is a baud rate that is the same for both the transmitting device and the receiving device.

There are also 2 more USART2 pins, UART2_CTS and UART2_RTS

These are pins that can stop the sending over of data in UART communication. They're for data flow control. The RTS pin of each device communicating via UART is cross coupled to the other's CTS pin. By placing the RTS pin to a HIGH logic state, the CTS pin of the device it is communicating with goes HIGH; this stops the module from sending the host data. Likewise, the module can stop the host sending data by taking its RTS HIGH, which takes the host's CTS HIGH.

The RTS and CTS require 2 extra wires when in configuration.

We will not be using them in our program.

Again, for this program, we will just be using the USART2_TX and USART2_RX pins, for use of the UART communication.

We don't actually have to do any connections at all.

The great thing about using the USART2 pins is that we can transmit or receive data using the UART protocol via USB.

So just connecting the STM32F446 board to your computer using a USB, you can intercept UART communication using a software. We will use the RealTerm software, which is a serial and TCP terminal for engineering and debugging.

We need 2 major code files in order for this code to work.

We need our header file, which contains many macros and structures that describe the various registers and needed values.

We then need our main C file, which contains the code that allows us to detect and register key presses with your computer's keyboard.

Below is the header file that we will need for our code, which in this case is named, stm32f407xx.h





So this header file contains all the definitions we need to create our main C file.

The contents of the main.c file is shown below.





The first thing we must do is include the stdint.h header file and our stm32f446xx.h header file in our main.c file.

Next we have a few function prototypes listed so that the compiler knows all of the functions in our program, the arguments they take in, the return value of the function, etc.

We then have a global keyword, key, of type char. This variable will store the character when we enable UART receiver communication and a user clicks a key on his/her keyboard.

After this, we have our main() function.

Before we go to this main() function, let's look at the function definitions, starting with the usart2_txrx_init() function.

This creates all the initializations needed in order to transmit or receive data using the UART protocol.

The first thing we do in this function is turn on the peripheral clock for GPIO Port A. We need this on because we are using the USART2_TX and USART2_RX pins located on this port.

We then set pin PA2 to alternate function mode using the mode register.

We then set pin PA2 to alternate function mode 7 (AF7). This makes this pin acts as USART2_TX.

Next we configure our USART2_RX pin.

We must configure pin PA3 to be alternate function 7 (AF7) in order to act as USART2_RX.

We first set pin PA3 to alternate function mode by the mode register.

We set the pin to AF7 to make it function as USART2_RX.

The next thing we do is we turn on the peripheral clock for USART2.

The next thing we do is we use a function, compute_uart_bd() to compute the baud rate for our device. Remember that we are using the USART pin for UART communication. UART communication depends on baud rate for proper communication between the host and the other device.

This function, which we will look at later, returns a 16-bit number that we place into the USART Baud Rate Register.

This register is shown below.


Baud rate register (USART_BRR) of an STM32F44 microcontroller board


Now we have our baud rate fixed for our UART transmission.

Now for the device you are communicating with in the UART protocol needs to have the baud rate fixed to the same value, so that we can have faultless communication.

Next, we have to enable the receiver for receiving UART communication.

This is done with the RE (Receiver Enable) bit, bit 2, of the USART control register 1.

The USART control register 1 is shown in the diagram below.


Control register 1 (USART_CR1) of an STM32F446 microcontroller board


By setting the RE bit to HIGH, we enable the receiver for receiving data via UART (or USART).

The final thing we must do is enable the USART communication. This is done with the UE pin, pin 13, of the USART control register 1. By setting this bit to HIGH, we enable USART communication. Once this is done, UART communication commences. This is why this is the last step.

Next we have our code for the compute_uart_bd() function.

You can see that this is a simple function based on the baud rate (which is 115200) and the peripheral clock (which is 16000000). This function returns a 16-bit number, which we used to feed into the USART Baud Rate Register.

Next, we have our uart2_read() function.

In this function, we have to first make sure that the read data register is not empty.

This can be done by checking the RXNE bit, bit 5, of the USART status register.

This register is shown in the diagram below.


Status register (USART_SR) of an STM32F446 microcontroller board


A 0 in the RXNE bit means that the register is empty and that there is nothing to read.

A 1 in the RXNE bit means that the received data is ready to be read.

We check the bit of RXNE by the following line, while(!((pUSART2->SR) & (1 << 5)));

While the RXNE bit is 0, the code stays within this loop. Once the RXNE bit is 1, the code exits the while loop and continues to the rest of the code.

This function reads and returns a single character, which is why it has a return type of char. This character gets written to the data register.

This data register holds 8 bits.

You can see this in the diagram below.


Data register (USART_DR) of an STM32F446 microcontroller board


Because this register holds 8-bits, it can only hold a single character at once.

We now go back to the main() function.

So we first have to turn on the peripheral clock for GPIOA before we can do anything else with this port.

We then set PA5 as output in the mode register, because we want to show that if the user types in a certain key, 'q' in this case, it will make the LED on the board connected to pin PA5 turn on.

We first do all initializations with the statement, usart2_txrx_init();

Within the infinite loop, we read in the character into the key variable.

If the character is equal to 'q', we turn on the onboard LED. If any other character, the LED is off.

This just demonstrates that we can not only read in a character through UART communication, but perform an action based on the character that was pressed.

As stated before, we use the RealTerm software to send the keypresses via UART communication.

In this case, our STM32 is receiving data from the RealTerm software.

When you run this program, run it in debug mode and insert the key variable into the Live Expressions.

Remember to set the Baud Rate to 115200 on the RealTerm software and to select the appropriate USB port on your computer.

You may have to press the 'Open' button to close and reopen the port to reset the software.

With the mouse cursor on the RealTerm software, you press the keys and they should be registered on the Live Expressions section of the STM32 software.

This is shown below.


STM32 live expressions with UART receiver communication


So you can see our program can detect the key pressed each time a user presses a key.

So this is how to receive data with the UART communication protocol with an STM32F446 microcontroller board.



Related Resources





HTML Comment Box is loading comments...