cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with UART and STM32F413ZH

JLask.1
Associate

Hello,

i have a problem and hope that someone can help me. I've been trying to find a solution for days now and I'm just not able to get any further.

I would like to set up a UART interface using register. Unfortunately nothing gets to the PC.

What I have tried so far:

UART2 Tx via PA2 and PD5 . Both unsuccessful.

Additionally I tried it over a FTDI USB. This also does not work

The registers look good, as far as I can see

I tried several terminals but no success

Here is my code:

#include "stdint.h"
#include "uart.h"
#include "stm32f413xx.h"
 
#define GPIOAEN				(1U<<0)
#define UART2EN				(1U<<17)
 
#define DBG_UART_BAUDRATE	9600
#define SYS_FREQ			16000000
#define APB1_CLK			SYS_FREQ
#define CR1_TE				(1U<<3)
#define CR1_UE				(1U<<13)
#define SR_TXE				(1U<<7)
 
static void uart_set_baudrate(uint32_t periph_clk, uint32_t baudrate);
static void uart_write(int ch);
 
int __io_putchar(int ch) {
	uart_write(ch);
	return ch;
}
 
void debug_uart_init(void){
 
	/* Enable clock acces to GPIOA */
	RCC->AHB1ENR |= GPIOAEN;
 
	/* Set the mode of PA2 to alternate function mode */
	GPIOA->MODER &= ~(1U << 4);
	GPIOA->MODER |= (1U << 5);
 
	/* Set alternate function type to AF7 (UART2_TX) */
	GPIOA->AFR[0] |= (1U << 8);
	GPIOA->AFR[0] |= (1U << 9);
	GPIOA->AFR[0] |= (1U << 10);
	GPIOA->AFR[0] &= ~(1U << 11);
 
	/* Enable clock access to UART2 */
	RCC->APB1ENR |= UART2EN;
 
	/* Configure UART baudrate */
	uart_set_baudrate(APB1_CLK, DBG_UART_BAUDRATE);
 
	/* Configure transfer direction */
	USART2->CR1 = CR1_TE;
 
	/* Enable UART Module */
	USART2->CR1 = CR1_UE;
}
 
static void uart_write(int ch){
 
	/* Make sure transmit data register is empty */
	while(!(USART2->SR & SR_TXE)){}
 
	/* Write to transmit data register */
	USART2->DR = (ch & 0xFF);
}
 
 
static uint16_t compute_uart_bd(uint32_t periph_clk, uint32_t baudrate){
	return ((periph_clk + (baudrate / 2U)) / baudrate);
}
 
static void uart_set_baudrate(uint32_t periph_clk, uint32_t baudrate){
	USART2->BRR = compute_uart_bd(periph_clk, baudrate);
}

The main.c has the following code

#include "stdio.h"
#include "stm32f413xx.h"
#include "fpu.h"
#include "uart.h"
  
int main()
{
 
	/* Enable FPU */
	fpu_enable();
 
	/* Initialize debug UART */
	debug_uart_init();
 
	while(1)
	{
		printf("Hello");
		for (int i = 0; i < 9000; ++i){}
	}
}

I would be really grateful if someone could help me find the problem

8 REPLIES 8

Isn't HSI 16 MHz ??

Perhaps get a scope look at signals on pins.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
JLask.1
Associate

Yes you are right HSI is 16MHz. i had also tried 16MHz and also just tried again now. unfortunately the same problem. I have also tried several terminals. MobaXterm, CoolTerm, RealTerm and Putty. 

Probably not an issue with the terminal applications, look at the signal itself, with a scope, perhaps output a continuous 'U' 0x55 pattern?

Review the register settings, per manual.

Try with a HAL example to sanity check the hardware is working as expected.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Chris21
Senior

It's odd that you have RCC->APB1ENR |= UART2EN; should be USART2EN.

USART2->CR1 = CR1_TE; // enable transmitter

/* Enable UART Module */

USART2->CR1 = CR1_UE; // disables transmitter

Probably want to be using |= ...

Piranha
Chief II
#include "stm32f413xx.h"
 
#define GPIOAEN				(1U<<0)
#define UART2EN				(1U<<17)
 
#define CR1_TE				(1U<<3)
#define CR1_UE				(1U<<13)
#define SR_TXE				(1U<<7)

32-bit platform needs an "ul/UL" suffix. But why are you redefining bit field definitions instead of using ST defined ones?

Because it's more efficient, and less error prone, like repeatedly accessing the same register..

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

One of the tricks with register level code is to let the COMPILER do a lot of heavy lifting ONCE at compile time, on a machine running at 3 GHz.

The compiler can fold up the math, it can't fold RMW action on VOLATILE memory, where it instead has to assure in-order-execution.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

As long as short defined names aren't unfortunately reused by other peripherals using the same implementation... or these defines are "local" to a C source file....