cancel
Showing results for 
Search instead for 
Did you mean: 

Bare Metal Programming STM32F103 USART not transmitting

Raymond Buck
Senior

I have been learning bare metal programming for STM32F103 for the last few days. I am using a bluepill board for testing. I have the clocks up and running at 72 MHz. I have successfully tested the GPIOs for correct operation as inputs and outputs. Now I am trying to get the USART working. If I use the HAL libraries to program the board with UART code it works so I know the hardware is functional.

I am starting out by trying to get the transmit part of the USART to send characters to my terminal program on the PC. After that works I will get the receive working. So far I have been unable to see any activity on the transmit line.

This is my USART1 setup code:

void setusart1(void)

{

   // 9600 Baud with 72 MHz clock USARTDIV value is 0x1D4C

   USART1->SR = 0x0000; // clear all flags and errors on startup

   AFIO->MAPR = (1<<2); // remap USART1 to PB6 and PB7

   RCC->APB2ENR |= (1<<14); // Enable USART1 clock

   // USART1_CR1 Reset value is 0x0000

   USART1->CR1 |= (1<<5); // Bit 5 - Enable RX interrupt

   USART1->CR1 |= (1<<3); // Bit 3 - Enable transmitter

   USART1->CR1 |= (1<<2); // Bit 2 - Enable receiver

   USART1->BRR = 0x1D4C; // 9600 Baud - enable after TE and RE are enabled

   USART1->CR1 |= (1<<13); // enable USART1 - Start, 8N1

   // USART1_CR2 Reset value 0x0000 - Bits 13:12 value 0:0 assigns 1 Stop bit

}

This is how I have the GPIOs setup for the USART.

//PB6 Alternate function output Open-drain,  PB7 Input mode floating input

GPIOB->CRL = 0x4D222222; // GPIOB0-B5 all push-pull outputs @ 2 MHz, PB6,PB7 ALT USART

In my main loop I am using this line of code to send the character "A" to the USART transmit buffer.

USART1->DR = 0x41;

I repeat this line in a loop every 500 msecs. I am also flashing a LED in the loop so I know the code is running.

What am I missing or doing wrong?

2 REPLIES 2

The USART1 clock needs to be enabled prior to touching any registers

The AFIO clock, and GPIOB clocks will also need to be enabled to remap and configure the pins.

Check the SR for TXE before writing DR, you will not be able to inspect the DR via the debugger, the read shows inbound data

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

Tesla DeLorean,

Thank you!

The USART1 clock was being enabled after setting up the registers. Also, the AFIO was not being enabled at all. I don't remember reading the AFIO clock had to be set but it should be apparent now that I think about it. The GPIOB clocks were being setup before calling the USART setup steps.

Out of curiosity I ran a test with the USART1 clock. I found it could be placed after programming the registers as long as it was placed before enabling the TE and RE bits in USART1->CR1. However, as good programming practice I will leave it as the first step in setting up the USART. The second step will be enabling the AFIO clock. Third step will be remapping PB6 and PB7. I will then setup all the other registers.

I also had to change PB6 from AF output open drain to AF output push-pull. I was getting a framing error in open drain mode.