I have code that initializes UART2 on the STM32F4 (and some other peripherals).
When the MCU completes initialization, it enters the USART2_IRQHandler and executes the Timer_Timeout_Enable function, so TIM3 starts counting and after some time (in this case, 10 microseconds), it sets the flag_msg_received. This triggers the received message processing function and generally allows the rest of the code in main.c to work.
The problem is that during MCU initialization, I am not receiving any messages via UART, and the MCU sends a message to the terminal stating that the received message is incorrect.
What could be the problem? How should I properly configure the UART to prevent the MCU from accepting the first garbage message?
Here is my main.c code:
#include "stm32f4xx.h"
#include "SystemClock_Config.h"
#include "SysTick_Init.h"
#include "UART2_Init.h"
#include "Exchange.h"
#include "TIMER_Init.h"
#include "TIMER_Timeout_Init.h"
int main(void)
{
Clear_Flag_Init();
SystemClock_Config();
SysTick_Init();
UART2_Init();
TIMER2_Init();
Timer_Timeout_Init();
RCC->AHB1ENR |=RCC_AHB1ENR_GPIODEN;
GPIOD->MODER |=GPIO_MODER_MODE12_0|GPIO_MODER_MODE13_0|GPIO_MODER_MODE14_0|GPIO_MODER_MODE15_0;
Set_Led_State();
Set_Flag_Init();
UART2_enable();
while(1)
{
if(get_flag_msg_received())
{
received_msg_processing();
}
Set_Led_State();
if(delay_msg())
{
send_response();
clear_flag_delay();
clear_error();
if(get_restart_flag()) restart_MCU();
}
}
}
UART_Init function:
void UART2_Init(void)
{
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; //USART2 Clk enable
USART2->BRR = 0x88C; //BR_target = F_APB2/(16*BRR)->BRR = F_APB2/(16*BR_target) = 42,000,000/(16*19200)=136,71875 -> Mantissa = 136(0x88), Fraction = 0,71875*16=11,5=12(0xС) ->BRR = 0x88C
USART2->CR1 |= USART_CR1_RE | USART_CR1_TE | USART_CR1_UE | USART_CR1_RXNEIE; //RX not empty interrupt, transmitter and reciever ARE ENABLE
USART2->CR1 &= ~(USART_CR1_M|USART_CR1_PCE); //word lengh = 8bit, parity control disable
USART2->CR2 &= ~(USART_CR2_STOP); //1 STOP BIT, CLK DISABLE - asynchronous mode
NVIC_EnableIRQ(USART2_IRQn); //Enable USART1 unterrupts in NVIC cintroller
//PD5 - TX, PD6 - RX
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; //GPIOA CLK ENABLE
GPIOD->MODER &= ~(GPIO_MODER_MODE5|GPIO_MODER_MODE6); //Reset MODER 5 and 6
GPIOD->MODER |= GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1; //Set MODER 5 and 6 in alter function
GPIOD->AFR[0] |= (7<<GPIO_AFRL_AFSEL5_Pos)|(7<<GPIO_AFRL_AFSEL6_Pos); //AFRH and AFRL registers are parts of array ARR[] ->AFRL = ARR[0], 7 - USART alt func selected by "selecting an alternate function" << on AFSELX_Pos
}
and UART2_enable function:
void UART2_enable(void)
{
USART2->CR1 |= USART_CR1_UE; //USART2 ENABLE
}
Your UART2_Init()
function enables the UART by setting USART_CR1_UE
.
It does this very early on, before the rest of the UART has been configured, and before your GPIO pins have been configured for the correct mode.
Therefore, the UART is being enabled while the GPIO pins are probably floating, and you'll likely receive garbage characters into the receive data register.
You should remove the setting of USART_CR1_UE
from UART2_Init()
, and enable it with your UART2_enable()
function once the UART configuration is complete (which I think is what you intended anyway).