Skip to main content
Visitor II
March 25, 2025
Solved

Problem with USART on Nucleo-F401RE

  • March 25, 2025
  • 1 reply
  • 536 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ƎALLEmAnswer
    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.