STM32F4 USART1无法正常工作并返回垃圾数据

时间:2018-08-16 23:37:35

标签: stm32 uart stm32f4discovery stm32f4 usart

我正在尝试使用STM32F407 USART1外设,但无法正常工作。我已经阅读了很多次数据表,但找不到任何解决方案。

我使用FTDI232进行通信。我的连接正确,我在MSP430上使用此连接。在代码中,我暂时不使用DMA,因为我目前不知道如何配置DMA(用于多次通信)。

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

我为几乎所有行添加了注释。 我的错误在哪里?你能帮我吗?

#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;  
}

4 个答案:

答案 0 :(得分:2)

这也可能是由于问题,与您的程序无关。如果将发现板与USART1一起使用,请注意,某些必需的引脚(PA9 / PA10)已在使用中。

一些其他信息here

答案 1 :(得分:0)

如果您尝试了@elasticman指出的解决方案,然后又得到了一堆垃圾数据,那么也可以按照以下建议进行检查。它是从this链接借来的。

  
      
  • (**)HSE_VALUE是在stm32f4xx.h文件中定义的常量   (默认值为25 MHz),用户必须确保HSE_VALUE与   所用晶体的实际频率。除此以外,   此功能可能有错误的结果。
  •   

在STM32F407发现板上使用的晶体为8MHz,因此将stm32f4xx.h文件(默认为25MHz)中的HSE_VALUE校正为8MHz非常重要,以确保USART能够正常工作。

答案 2 :(得分:0)

请尝试将AHB时钟更改为64 MHz,然后添加更多的预标量,以使APB1低于42MHz。我不知道原因,但超过64MHz则不起作用。

答案 3 :(得分:0)

我想我有个解决办法。如果您拉起gpio针

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;    

无论ST实施了何种外围过载,都可以使USART1(连接到我板上的st-link)工作。

(编辑):我看到您已经将PUPDR设置为上拉,如果不能解决此问题,对不起,但是确实解决了我的问题。顺便说一下,我正在使用STM32F429Disc1板。