2023-04-03 11:21 AM
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
2023-04-03 11:37 AM
Isn't HSI 16 MHz ??
Perhaps get a scope look at signals on pins.
2023-04-03 11:44 AM
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.
2023-04-04 08:19 AM
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.
2023-04-04 09:34 AM
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 |= ...
2023-04-04 02:12 PM
#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?
2023-04-04 02:16 PM
Because it's more efficient, and less error prone, like repeatedly accessing the same register..
2023-04-04 02:21 PM
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.
2023-04-04 07:41 PM
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....