STM32F4 USART1 不能正常工作,return 垃圾数据
STM32F4 USART1 doesn't work correctly and return garbage data
我正在尝试使用 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;
}
这也可能是问题,与您的程序无关。如果您将 Discovery 板与 USART1 一起使用,请注意一些必需的引脚 (PA9 / PA10) 已被使用。
一些进一步的信息here。
如果您尝试了@elasticman 指出的解决方案并再次得到一堆垃圾数据,那么也可以检查以下建议。它是从 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.
STM32F407发现板中已经使用的crystal为8MHz所以重要的是将stm32f4xx.h文件中的HSE_VALUE(默认为25MHz)修正为8MHz以确保USART 将正常工作。
请尝试将 AHB 时钟更改为 64 MHz,然后添加更多预标量以使 APB1 低于 42MHz 我不知道原因,但超过 64MHz 它不起作用。
我想我有解决办法。如果你拉起你的 gpio 引脚
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
你可以让 USART1(它连接到我的板子中的 st-link)工作,不管 ST 实现的外设过载。
(edit):我看到您已经将 PUPDR 设置为 pullup,很抱歉,如果没有解决这个问题,但它确实解决了我的问题。顺便说一句,我正在使用 STM32F429Disc1 开发板。
我正在尝试使用 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;
}
这也可能是问题,与您的程序无关。如果您将 Discovery 板与 USART1 一起使用,请注意一些必需的引脚 (PA9 / PA10) 已被使用。
一些进一步的信息here。
如果您尝试了@elasticman 指出的解决方案并再次得到一堆垃圾数据,那么也可以检查以下建议。它是从 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.
STM32F407发现板中已经使用的crystal为8MHz所以重要的是将stm32f4xx.h文件中的HSE_VALUE(默认为25MHz)修正为8MHz以确保USART 将正常工作。
请尝试将 AHB 时钟更改为 64 MHz,然后添加更多预标量以使 APB1 低于 42MHz 我不知道原因,但超过 64MHz 它不起作用。
我想我有解决办法。如果你拉起你的 gpio 引脚
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
你可以让 USART1(它连接到我的板子中的 st-link)工作,不管 ST 实现的外设过载。
(edit):我看到您已经将 PUPDR 设置为 pullup,很抱歉,如果没有解决这个问题,但它确实解决了我的问题。顺便说一句,我正在使用 STM32F429Disc1 开发板。