AnsweredAssumed Answered

Need help with USART on Nucleo STM32f411.

Question asked by sohail on Oct 8, 2015
Latest reply on Oct 10, 2015 by sohail
I'm trying to set up communication between the USART2 on stm32f411xe nucleo and a PC using the STLink Virtual COM Port (COM3). I'm avoiding the ST HAL or Standard Peripheral Library as a beginner as far as possible. The relevant code is as under:

main.c:
...
...
    usart2Init();
    
    usart2PutChar('C');
    while(1)
    {
        userLedToggle();
        delayMs(500);
    }
...
...

void usart2Init(void)
{
    uint32_t temp = 0x0;
    static uint8_t usart2Initialized = 0x0;
    
    if(!usart2Initialized)
    {
        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

        temp = GPIOA->MODER;
        temp &= ~(GPIO_MODER_MODER2 | GPIO_MODER_MODER3);
        temp |= ((GPIO_MODE_AF << 4) | (GPIO_MODE_AF << 6));
        GPIOA->MODER = temp;

        GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_2 | GPIO_OTYPER_OT_3);
        GPIOA->OTYPER |= ((GPIO_OTYPE_PP << 4) | (GPIO_OTYPE_PP << 6));

        temp = GPIOA->OSPEEDR;
        temp &= ~(GPIO_OSPEEDER_OSPEEDR2 | GPIO_OSPEEDER_OSPEEDR3);
        temp |= ((GPIO_SPEED_HIGH << 4) | (GPIO_SPEED_HIGH << 6));
        GPIOA->OSPEEDR = temp;

        temp = GPIOA->PUPDR;
        temp &= ~(GPIO_PUPDR_PUPDR2 | GPIO_PUPDR_PUPDR3);
        temp |= ((GPIO_PUPD_NONE << 4) | (GPIO_PUPD_NONE << 6));
        GPIOA->PUPDR = temp;

        temp = GPIOA->AFR[0];
        temp &= ~(GPIO_AFRL_AFRL_2 | GPIO_AFRL_AFRL_3);
        temp |= ((GPIO_AF7_USART2 << 8) | (GPIO_AF7_USART2 << 12));
        GPIOA->AFR[0] = temp;

        RCC->APB1ENR |= RCC_APB1ENR_USART2EN;

        USARTConfig_Typedef USARTConfig;
        USARTConfig.baudRate = 9600;
        USARTConfig.mode = (USART_CONFIG_MODE_TX);
        USARTConfig.parity = USART_CONFIG_PARITY_NONE;
        USARTConfig.wordLength = USART_CONFIG_WL8;
        USARTConfig.stopBits = USART_CONFIG_SB_20;
        USARTConfig.overSampling = USART_CONFIG_OS16;
        usart2Config(&USARTConfig);

        usart2Initialized = 0x1;
    }
}

void usart2Config(USARTConfig_Typedef * c)
{
    uint32_t temp = 0x0;
    
    USART2->CR1 |= USART_CR1_UE;
    
    temp = USART2->CR1;
    temp &= ~(USART_CR1_OVER8 | USART_CR1_M | USART_CR1_PS | USART_CR1_PCE);
    temp |= (c->mode | c->wordLength | c->parity | c->overSampling);
    USART2->CR1 = temp;
    
    temp = USART2->CR2;
    temp &= ~USART_CR2_STOP;
    temp |= c->stopBits;
    USART2->CR2 = temp;
    
    USART2->BRR = USART_BRR(getAPB1ClkFreq(), c->baudRate);
    
    USART2->CR1 |= c->mode;
}

void usart2PutChar(uint8_t d)
{
    while(!(USART2->SR & USART_SR_TXE))
        ;
    
    USART2->DR = (d & (uint8_t)0xFF);
}

With this code, the data on Realterm and PuTTY on the PC is garbled. The configuration is the same on both ends:

Baud Rate:                   9600
Databits (Word Length): 8
Stopbits:                     2

I've tried various baud rates/stop bits and verified the configuration each time by reading the USART2_BRR, USART2_CR1/2/3 registers but to no good. If it helps, the data that appears as 'Binary' on Realterm is 11111110 00011110 11111110.

Any pointers would be very helpful. Thanks.

Outcomes