I started working with with stm32f103c8t6 recently and I was able to set GPIO to input and output, however when I try to set USART it just does not work. I'm trying to write directly to registers, because I would like to understand how things work on the lower level, but I do realise that there are some helper libraries for working with USART.

Anyway I follow instructions from: Official reference manual on how to get USART Transmission working, but the code does not work, there is nothing in USART terminal on my PC. I do realise there is a lot of room for error. Here is my code for initializing and sending USART Transmission on stm32f103c8t6:

void initUartTransmission(){
    //1. Enable the USART by writing the UE bit in USART_CR1 register to 1.
    USART1 -> CR1 |= (0x1 << 13);
    //2. Program the M bit in USART_CR1 to define the word length.
    USART1 -> CR1 &= ~(0x1 << 12);
    //3. Program the number of stop bits in USART_CR2.
    USART1 -> CR2 &= ~(0x1 << 12);
    USART1 -> CR2 &= ~(0x1 << 13);
    // 4. Select DMA enable (DMAT) in USART_CR3 if Multi buffer Communication is to take
    // place.
    // I'm skipping this, because I'm not interested in DMA at this time
    // 5. Select the desired baud rate using the USART_BRR register.
    // I'm not certain of the clock speed I have. The board has 8 MH cristal,
    // but I'm not sure if it's enabled
    float f = ((float)(8000000/16)/9600);
    int q = (((int)f)&0x0FFF);
    int k = (float)(f - (float)q);
    k = (float)(k * 16);
    USART1 -> BRR = ((q<<0)|(((int)k&0x0F)<<8));
    //6. Set the TE bit in USART_CR1 to send an idle frame as first transmission.
    USART1 -> CR1 |= (0x1 << 3);
    //Enable clock for USART1

void void writeUart(){
    while(!(USART1 -> SR & (1<<7))){
        USART1->DR = 'c';

I've been trying different configurations, but I just couldn't get it to work. I am confident in connections between the board and my USB USART adapter, because I have experience with Atmega328p.

I would appreciate any help.

  • 1
    \$\begingroup\$ was stuck there too. Can't write whole answer but this may help github.com/Manyyack/STM32/tree/master/UART/src \$\endgroup\$
    – MaNyYaCk
    Feb 12, 2019 at 10:19
  • \$\begingroup\$ There's no need for the messy floating point math to calculate baud rate. Simply set USART1_BRR = PCLK1 + ((BAUD_RATE) >> 1) / BAUD_RATE, i.e. for PCLK1= 8000000 it yields (8000000 + 4800) / 9600 = 833. \$\endgroup\$
    – neoxic
    Feb 19, 2023 at 23:40

2 Answers 2


Enable the peripherals in RCC first, both the UART and the I/O port. (Port A if using the default pin mapping.) Until that point the peripherals are completely disabled, including their register interface, writes to USART1->CR1 etc have no effect. This line should go to the top:


Configure GPIO alternate output

All pins are in input mode at reset. To enable the output signal on the TX pin, you should set PA9 to

  • Output mode, (max speed 2 MHz)
  • Alternate function output push-pull

See the description of GPIOA->CRL/GPIOA->CRH in the reference manual for the bit settings.


The register writes are ignored because the last thing you do is enable the peripheral clock.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.