2022-01-04 09:47 AM
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?
2022-01-04 10:04 AM
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
2022-01-04 11:06 AM
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.