Electrical – USART not working with CP2102 adapter and STM32F1 Blue Pill board

cp2102stm32stm32f1stm32f103c8t6

Having programmed 8-bit AVR MCU's, I bought Blue Pill STM32F103C8 dev board from ebay. It has 8MHz external crystal and I program it with ST-Link on Mac. I saw a lot of options like HAL, etc, but I chose to program using direct access to registers and with core of CMSIS.

My problem is that I am trying to send symbol from MCU to computer. I am using CP2102 module connected to USART1(PB6 and PB7). LEDs are blinking, but I don't get any output in Arduino IDE serial monitor. Here is my code:

#include "stm32f1xx.h"

void delay(unsigned long delay)
{
    while(delay) delay--;
}

int SendChar (int ch)  {
    while (!(USART1->SR & USART_SR_TXE));
    USART1->DR = (ch & 0xFF);
    return (ch);
}

int main(void)
{
    //Enable I2C2 clock
    RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;
    //Enable the clock to PORT B, PORT C, USART1 and AFIO clocks
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN |       RCC_APB2ENR_AFIOEN;
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;

    //use AFIO_MAPR register to remap alternate functions to use USART 1 TX and RX on PB6 and PB7
    //Ref 7.4.2 and 6.3.7 in st manual
    AFIO->MAPR |= AFIO_MAPR_USART1_REMAP;

    //CRL Configures outputs 0 to 7 and CRH 8 to 15, so if you want to configure PC13,
    //you modify GPIOC_CRH register
    GPIOB->CRL |= GPIO_CRL_MODE0_0 | GPIO_CRL_MODE0_1;
    GPIOC->CRH = GPIO_CRH_MODE13_0 | GPIO_CRH_MODE13_1 |
        GPIO_CRH_MODE14_0 | GPIO_CRH_MODE14_1 |
        GPIO_CRH_MODE15_0 | GPIO_CRH_MODE15_1;
    //Set RX as floating in and TX as out push-pull
    GPIOB->CRL &= ~(GPIO_CRL_MODE7_0 | GPIO_CRL_MODE7_1);
    GPIOB->CRL |= GPIO_CRL_MODE7_0 | GPIO_CRL_MODE7_1 | GPIO_CRL_CNF6_0;

    //Enable RX TX
    USART1->CR1 |= (USART_CR1_RE | USART_CR1_TE);  // RX, TX enable
    //Enable USART
    USART1->CR1 |= USART_CR1_UE;
    //Make sure to clear OVER8 bit(15 bit in USART_CR1) to oversample by 16, I dont know if I need this
    USART1->CR1 &= ~(1 << 15);
    ////Configure Baud Rate
    /*USART_BRR = Fck/BAUDRATE*/
    //Set 115200 Baud, 8 MHz crystal
    USART1->BRR = 8000000L/115200L;

    while (1)
    {
        SendChar(35); //Test UART,fingers crossed

        //Toggle led on PB0
        GPIOB->ODR ^= GPIO_ODR_ODR0;

        //Toogle RGB led connected on PC13, PC14 and PC5
        GPIOC->ODR ^= GPIO_ODR_ODR13;
        delay(50000);
        GPIOC->ODR ^= GPIO_ODR_ODR13;
        delay(50000);
        GPIOC->ODR ^= GPIO_ODR_ODR15;
        delay(50000);
    }

    return 0;
}

Best Answer

I have managed to solve problem with the help of cheap USB Logic Analyser and STM32 reference manual. I was setting GPIO pins for USART1 incorrectly, RX needs to be floating input and TX needs to be alternate function output with pull-up/pull-down. So after changing these lines:

 GPIOB->CRL &= ~(GPIO_CRL_MODE7_0 | GPIO_CRL_MODE7_1);
 GPIOB->CRL |= GPIO_CRL_MODE7_0 | GPIO_CRL_MODE7_1 | GPIO_CRL_CNF6_0;

To:

GPIOB->CRL |= GPIO_CRL_MODE6_1 | GPIO_CRL_CNF6_1 | GPIO_CRL_CNF7_0;

I can see character being sent with logic analyzer hooked up and also can observe it on arduino serial monitor.

Related Topic