STM32F4 USART1 doesn't work correctly and return garbage data

2

I am trying to work with STM32F407 USART1 peripheral but it doesn't work correctly. I have read the datasheet for many times but i couldn't find any solution.

I use FTDI232 for the communication. My connections are correct, i use this connection on MSP430. In the code, i don't use DMA for now because i don't know how to configure DMA currently (for multiple communication).

FTDI232 RX Pin ---> PA9 (STM32407 USART1 TX)
FTDI232 TX Pin ---> PA10 (STM32407 USART1 RX)
FTDI232 Ground ---> STM32F407 Ground

I have added comments for almost all lines. Where is my mistake? Could you help me?

#include "stm32f4xx.h"                  // Device header
#include "stm32f4xx_hal.h"              // Keil::Device:STM32Cube HAL:Common

/************************************************************ 
    CPU  Frequency  168Mhz
    AHB  Frequency  168MHz
    APB1 Frequency  42MHz
    APB2 Frequency  84MHz
************************************************************/

/************************* PLL Parameters *************************************/
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      8
#define PLL_N      336

/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2

/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7

/******************************************************************************/

#define CPU_PLL_CLK             168000000UL         // 168 MHz
#define AHB_BUS_CLK             168000000UL         // 168 MHz
#define APB1_BUS_CLK            42000000UL          // 42  MHz
#define APB2_BUS_CLK            84000000UL          // 84  MHz

// USART1 Functions
void            USART1_Init(uint32_t baudrate);
void            USART1_WriteChar(uint8_t data);

// Delay with MS
// Every Cycle = 5.95 ns (for 168 MHz)
void delay_ms(uint32_t delay_time)
{   
    delay_time *= (CPU_PLL_CLK / 1000) / 5.95;
    while(delay_time--);
}

/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
     SYSCLK = PLL_VCO / PLL_P
*/ 
void System_Config(void)
{

    RCC->CFGR        = 0x00000000;                  // CFGR All Cleared - System Clock HSI
    RCC->CFGR           |=  (4    << 10);           // PPRE1 - APB1 - AHB clock divided by 2
    RCC->CFGR           |=  (4    << 13);           // PPRE2 - APB2 - AHB clock divided by 2
    RCC->CR             |=  (1    << 16);           // HSEON - HSE External Oscillator

    while (!(RCC->CR & 0x00020000));        // HSERDY - Wait HSE active

    RCC->PLLCFGR    |=  (8      <<  0);         // PLLM = 8;
    RCC->PLLCFGR    |=  (336    <<  6);         // PLLN = 336;
    RCC->PLLCFGR    &= ~(3    << 16);           // PLLP = 2;    For 2, write 00
    RCC->PLLCFGR    |=  (7      << 24);         // PLLQ = 7;

    RCC->CR             |=  (1    << 24);           // PLLON - PLL Active

    while (!(RCC->CR & 0x02000000));        // PLLRDY - Wait PLL active

    FLASH->ACR      |=  (5    <<  0);           // Wait State = 5
    FLASH->ACR      |=  (1    <<  9);           // Data Cache active
    FLASH->ACR      |=  (1    << 10);           // Instruction Cache active

    RCC->CFGR       |=  (2    <<  0);     // System Clock PLL

    while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Wait until load

}

int main(void)
{

    System_Config();
    USART1_Init(115200);        // Parameter Not Used Now

    while(1)
    {
        USART1_WriteChar('a');
        delay_ms(1000);
    }

    return 0;
}

/*
    Tx/Rx baud = fCLK / (8 * (2 - OVER8) * USARTDIV)
                                OVER8 -> CR1 Register 15. Bit (Over Sampling)
                                fCLK = SystemClock
    8000000 / (16 * 9600)
*/
void USART1_Init(uint32_t baudrate)
{

    /* GPIOA clock enable */
    RCC->AHB1ENR        |= (1UL << 0);                                              //  RCC_AHB1ENR_GPIOAEN;

    // AFR[0] = AFRL Register   - Address 0x20
    // AFR[1] = AFRH Register   - Address   0x21
    // GPIOA->AFR[1] |= (0x00000110);   

    GPIOA->MODER    |=  (2UL << 18);                                                // GPIO_AFRH_AFRH0 - PA9  - Alternate State 
    GPIOA->MODER    |=  (2UL << 20);                                                // GPIO_AFRH_AFRH1 - PA10 - Alternate State

    GPIOA->PUPDR &= ~((3 << 18) | (3 << 20));                               // No Pull UP/DOWN
    GPIOA->PUPDR |=   (1 << 18) | (1 << 20);                                // Pull UP

    GPIOA->AFR[1]   &= ~(15UL << 4);                                                // Clear AF Mode
    GPIOA->AFR[1]   &= ~(15UL << 8);                                                // Clear AF Mode
    GPIOA->AFR[1]   |=  (7UL << 4);                                                 // GPIO_AFRH_AFRH0 - PA9
    GPIOA->AFR[1]   |=  (7UL << 8);                                                 // GPIO_AFRH_AFRH1 - PA10

    // USART1 clock enable
    RCC->APB2ENR        |= (1UL << 4);                                                  // Enable USART1 - RCC_APB2ENR_USART1EN;
    //RCC->APB2RSTR     |= (1UL << 4);  
    //RCC->APB2RSTR     &= ~(1UL << 4);                                             // USART1 Disable Reset Mode    

    USART1->CR2 &= ~(3 << 12);      // USART_STOPBITS_1

    USART1->CR1 &= ~(1 << 12);      //  USART_WORDLENGTH_8B
    USART1->CR1 &= ~(1 << 10);      //  USART_PARITY_NONE
    USART1->CR1 |=  (1 <<  7);      //  USART_CR1_TXEIE
    USART1->CR1 |=  (1 <<  5);      //  USART_CR1_RXNEIE
    USART1->CR1 |=  (1 <<  3);      //  USART_MODE_TX
    USART1->CR1 |=  (1 <<  2);      //  USART_MODE_RX

    //USART1->BRR     = SystemCoreClock / (16 * 115200);            // 115200 baud
    //USART1->BRR  = 84000000 / (16 * 115200);
    USART1->BRR  = 0x2D9;                     // 115200

    /* Enable the USART */
    USART1->CR1 |=  (1 <<  13);     //  USART_CR1_UE

    NVIC->ISER[1] = 1 << (USART1_IRQn - 32);        // USART1 Global Interrupt Enable
    //NVIC->ISER[1]  |= 0x20;                           // USART1 Interrupt Enable      

    //USART1->SR &= ~(0x40);                          // Status Register

}

void USART1_WriteChar(uint8_t data)
{
    while(!(USART1->SR & 0x80));      // USART_SR_TXE - USART_FLAG_TXE
    USART1->DR = data;  
}
stm32
uart
stm32f4discovery
stm32f4
usart
asked on Stack Overflow Aug 16, 2018 by Hasan Eren Keskin • edited Nov 19, 2018 by Amin Rostami

4 Answers

3

This might also be due to a problem, that has nothing to do with your program. If you use the Discovery board with USART1, please note that some required pins (PA9 / PA10) are already in use.

Some further information here.

answered on Stack Overflow Aug 20, 2018 by elasticman
0

If you tried the solutions that @elasticman point out and again you get a bunch of garbage data, that's good to check following recommendation too. It's borrowed from this link.

  • (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value 25 MHz), user has to ensure that HSE_VALUE is same as the real frequency of the crystal used. Otherwise, this function may have wrong result.

The crystal has been used in STM32F407 discovery board is 8MHz so it is important to correct the HSE_VALUE in the stm32f4xx.h file (by default is 25MHz) to 8MHz to ensure that USART will work correctly.

answered on Stack Overflow Nov 15, 2018 by Amin Rostami • edited Nov 17, 2018 by Amin Rostami
0

Please try to change AHB clock as 64 MHz and then add further pre scalar to bring APB1 under 42MHz I don't know the reason but over 64MHz it doesn't work.

answered on Stack Overflow Dec 5, 2018 by Soofiyan Atar
0

I think I have a fix. If you pull up your gpio pin

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;    

you could get USART1 (which is connected to the st-link in my board) to work, regardless of the peripheral overload implemented by ST.

(edit): I see that you already set the PUPDR to pullup, sorry if doesn't solve this problem, but it did solve mine. I'm working with a STM32F429Disc1 board by the way.

answered on Stack Overflow Dec 29, 2019 by Abdallah Rezgui • edited Dec 29, 2019 by Abdallah Rezgui

User contributions licensed under CC BY-SA 3.0