cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 UART Baremetal

HWin.1
Associate

Hey guys, I've been playing around with STM32F334R8 Nucleo board's USART module. As a part of it, I have written a small bare-metal code to print a character and unfortunately, my code isn't working. I am seeing junk on my putty window sometimes and it's remaining blank on some other times. Here is my code

#include "stm32f3xx.h"         // Device header
 
 
 
void delay(int n)
 
{
 
	for(int i=0;i<n*1000000;i++){} //Gives 1 second delay
 
}
 
 
 
void Init(void)
 
{
 
	RCC->AHBENR |= (1<<17); 
 
	RCC->APB1ENR |= (1<<17);
 
	GPIOA->AFR[0] |= 0x0700;
 
	GPIOA->MODER |= (1<<5);
 
	
 
	USART2->BRR = ((SystemCoreClock*2)/9600); //16MHz Frequency
 
	USART2->CR1 = (1<<3);
 
	USART2->CR1 |= (1<<0);
 
}
 
 
 
 
 
int main(void)
 
{
 
	Init();
 
	while(!(USART2->ISR & (1<<7))){};
 
	for(int i=0;i<50;i++)
 
	{
 
	USART2->TDR = 'K' & 0xFF;
 
	delay(1);
 
	}
 
}

Please let me know where I am going wrong. Thank you.

7 REPLIES 7

Try 19200 baud in putty, the bus definitely isn't running at twice the core.

Have the iterator in the delay as volatile to reduce chance of optimizer folding it.

The default HSI clock is surely 8 MHz

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

Observe the Tx pin using oscilloscope/LA.

Suspect hardware problems, including inadequate ground connection between mcu and PC. How do you connect mcu and PC, btw?

Use a terminal software which can display the incoming character as binary/hex, e.g. Bray's.

> for(int i=0;i<n*1000000;i++){} //Gives 1 second delay

Maybe not. Qualify i as volatile.

Are you sure about SystemCoreClock ? Try using a constant representing your cliock. You surely use the default clock (i.e. got rid of whatever your toolchain pushes onto you in the startup code as far as clocks are concerned), or checked the system/APB clock otherwise (output to MCO and observe using scope/LA).

I prefer using symbols from the CMSIS-mandated device header to "magic numbers" written to registers.

JW

HWin.1
Associate

Guys I have got the module working right now...but I want to know why should I put the following line to send my character.

USART2->TDR = 'K' & 0xFF;

Can't it be just

USART2->TDR = 'K' 

Why do we need to perform a bitwise and with 0xFF?

And what happens when you don't perform that & 0xFF?

JW

Because the register is arguably 9-bits wide. Don't think you need it here, but if you were using parity you'd definitely want to strip it on the RDR side because the hardware passes it to you.

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

The written code IMHO a bug magnet. Besides the SW delay for waiting seconds,

If the USART on the chip aso has FIFOs (gen 3) then the way to write the data register will matter.

Have a look at Tilen's git code for USART, SW FIFO, AT Commands (for RF modules) which might inspire you and shorten the learning curve.

https://github.com/MaJerle

turboscrew
Senior III

USART2 is on APB1 and the manual says: "he maximum frequency of the AHB and APB2 domains is 72 MHz. The maximum allowed frequency of the APB1 domain is 36 MHz."

Also, forget doubling the clock in the baud rate formula, because you don't have the OVER8 set.

In that chip, USART has no FIFO, and the data registers are 9-bit the msb being parity.

If parity is not enabled, seems like there can be 9-bit data.