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;
}
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.
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.
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.
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.
User contributions licensed under CC BY-SA 3.0