Skip to main content
Associate II
March 25, 2025
Solved

Problem with USART on Nucleo-F401RE

  • March 25, 2025
  • 1 reply
  • 560 views

Hi, I am pretty new to STM32 MCUs and I am having trouble with USART communication. I would like to send a message from Nucleo-F401RE to raspberry pi 3b+, and then to display that message in terminal on raspberry. I have tried to use USART2 for this but it didn't work, then i read that USART2 is used when i connect Nucleo to the laptop so i changed the code to use USART1 and it still doesn't work.

I have tested the USART2 with the advanced serial monitor on the laptop and it works properly.

Bellow are the functions in main.c and uart.c that i am currently using

This is the function uart.c, for some reason i couldn't post it as the attachment:

#include "moduli/uart.h"
#include "stm32f401xe.h"

#define BUFFER_SIZE 64

static uint8_t ring_buffer[BUFFER_SIZE];
static uint8_t rb_write;
static uint8_t rb_read;

void uart1_init() {
/*
* PA9 --> USART1 TX (AF7)
* PA10 --> USART1 RX (AF7)
*/
 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
 RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

 // Init GPIO
 GPIOA->MODER &= ~(0b11 << (9 * 2) | 0b11 << (10 * 2));
 GPIOA->MODER |= (0b10 << (9 * 2) | 0b10 << (10 * 2));

 GPIOA->AFR[1] &= ~(0xF << ((9 - ‌‌ * 4) | 0xF << ((10 - ‌‌ * 4));
 GPIOA->AFR[1] |= (7 << ((9 - ‌‌ * 4) | 7 << ((10 - ‌‌ * 4));

 // Init USART1
 USART1->CR1 &= ~(1 << 15); // OVER8 = 0 (16 samples)
 USART1->CR1 &= ~(1 << 12); // 8 data bits
 USART1->CR1 &= ~(1 << 10); // no parity
 USART1->CR1 |= (1 << 5); // RXNE interrupt enable
 USART1->CR1 |= (1 << 3); // TE
 USART1->CR1 |= (1 << 2); // RE

 // Baudrate: 9600 @ 42 MHz
 USART1->BRR = (273 << 4) | 7;

 USART1->CR1 |= (1 << 13); // USART enable

 NVIC->ISER[1] |= (1 << (37 - 32)); // USART1 IRQ
}

void uart1_send_data(unsigned char data) {
 while (!(USART1->SR & (1 << 6))); // TXE
 USART1->DR = data;
}

void uart1_send_data_array(unsigned char *data, unsigned int size) {
 for (int i = 0; i < size; i++) {
 uart1_send_data(*data++);
 }
}

void uart1_echo() {
 if (rb_read == rb_write)
 return;

 while (ring_buffer[rb_read] != '\0') {
 uart1_send_data(ring_buffer[rb_read]);
 rb_read = (rb_read + 1) % BUFFER_SIZE;
 }
}

void USART1_IRQHandler(void) {
 if ((USART1->SR & (1 << 5)) != 0) { // RXNE
 ring_buffer[rb_write] = USART1->DR;
 rb_write = (rb_write + 1) % BUFFER_SIZE;
 ring_buffer[rb_write] = '\0';
 }
}

 

Can somebody help me with this?

Thanks in advance.

 

Code formatting applied - please see How to insert source code for future reference.

This topic has been closed for replies.
Best answer by mƎALLEm

Hello,


@david027 wrote:

Hi, I am pretty new to STM32 MCUs and I am having trouble with USART communication.


As you are a newbie to STM32 MCUs, better to start by using the HAL and inspire from the examples provided in STM32CubeF4 package:

https://github.com/STMicroelectronics/STM32CubeF4/tree/master/Projects/STM324xG_EVAL/Examples/UART

https://github.com/STMicroelectronics/STM32CubeF4/tree/master/Projects/STM32F401RE-Nucleo/Examples/UART/UART_Printf

Then if you succeed with that you can inspire from the HAL implementation to develop your specific direct access to the registers.

1 reply

mƎALLEm
mƎALLEmBest answer
ST Technical Moderator
April 3, 2025

Hello,


@david027 wrote:

Hi, I am pretty new to STM32 MCUs and I am having trouble with USART communication.


As you are a newbie to STM32 MCUs, better to start by using the HAL and inspire from the examples provided in STM32CubeF4 package:

https://github.com/STMicroelectronics/STM32CubeF4/tree/master/Projects/STM324xG_EVAL/Examples/UART

https://github.com/STMicroelectronics/STM32CubeF4/tree/master/Projects/STM32F401RE-Nucleo/Examples/UART/UART_Printf

Then if you succeed with that you can inspire from the HAL implementation to develop your specific direct access to the registers.

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.