cancel
Showing results for 
Search instead for 
Did you mean: 

CLOSED - USART receiver not working on F446RE MCU

FGiai.1
Associate II

Hello all,

I'm trying to implement a really simple exercise:

  1. Send a char via USART2 (PA2);
  2. Receive the char via USART1 (PA10);
  3. After the char is received, within an interrupt I increase a variable called "Debug".

The only HW connection done is that between PA2 and PA10.

The send process works correctly, because I can see the char sent via USART2 in the console.

At the contrary, the part related to the receiver doesn't work. I don't see in any case the Debug variable increasing.

Can someone help me to the debug the code (see below)?

Thank you in advance,

Federico.

#include "main.h"
 
/* Initialize GPIO PA2 pin */
void GPIO_Init_PA2(void)
{
	/* Enable IO port A clock */
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
 
	/* Configure the I/O direction mode */
	// 10: Alternate function mode
	GPIOA->MODER &= ~GPIO_MODER_MODE2_0;
	GPIOA->MODER |=  GPIO_MODER_MODE2_1;
 
	/* Configure the I/O alternate function */
	// 0111: AF7 (i.e. USART2_TX for GPIO PA2 pin)
	GPIOA->AFR[0] |=  GPIO_AFRL_AFRL2_0;
	GPIOA->AFR[0] |=  GPIO_AFRL_AFRL2_1;
	GPIOA->AFR[0] |=  GPIO_AFRL_AFRL2_2;
	GPIOA->AFR[0] &= ~GPIO_AFRL_AFRL2_3;
}
 
/* Initialize USART USART2 */
void USART_Init_USART2(void)
{
	/* Enable USART2 clock */
	RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
 
	/* Enable USART2 */
	USART2->CR1 |= USART_CR1_UE;
 
	/* Select the word length */
	// 0: 1 Start bit, 8 Data bits, n Stop bits
	USART2->CR1 &= ~USART_CR1_M;
 
	/* Select number of stop bits */
	// 00: 1 Stop Bit
	USART2->CR2 &= ~USART_CR2_STOP_0;
	USART2->CR2 &= ~USART_CR2_STOP_1;
 
	/* Select the baud rate */
	USART2->BRR = (8 << 4) | 10;
 
	/* Select parity */
	// 0: Even parity
	//USART2->CR1 &= ~USART_CR1_PS;
 
	/* Enable transmitter */
	USART2->CR1 |= USART_CR1_TE;
}
 
/* Initialize GPIO PA10 pin */
void GPIO_Init_PA10(void)
{
	/* Enable IO port A clock */
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
 
	/* Configure the I/O direction mode */
	// 10: Alternate function mode
	GPIOA->MODER &= ~GPIO_MODER_MODE10_0;
	GPIOA->MODER |=  GPIO_MODER_MODE10_1;
 
	/* Configure the I/O alternate function */
	// 0111: AF7 (i.e. USART1_RX for GPIO PA10 pin)
	GPIOA->AFR[1] |=  GPIO_AFRH_AFSEL10_0;
	GPIOA->AFR[1] |=  GPIO_AFRH_AFSEL10_1;
	GPIOA->AFR[1] |=  GPIO_AFRH_AFSEL10_2;
	GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL10_3;
}
 
/* Initialize USART USART1 */
void USART_Init_USART1(void)
{
	/* Enable USART1 clock */
	RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
 
	/* Enable USART1 */
	USART1->CR1 |= USART_CR1_UE;
 
	/* Select the word length */
	// 0: 1 Start bit, 8 Data bits, n Stop bits
	USART1->CR1 &= ~USART_CR1_M;
 
	/* Select number of stop bits */
	// 00: 1 Stop Bit
	USART1->CR2 &= ~USART_CR2_STOP_0;
	USART1->CR2 &= ~USART_CR2_STOP_1;
 
	/* Select the baud rate */
	USART1->BRR = (8 << 4) | 10;
 
	/* Select parity */
	// 0: Even parity
	//USART1->CR1 &= ~USART_CR1_PS;
 
	/* Enable RXNE interrupt */
	// 1: An USART interrupt is generated whenever ORE=1 or RXNE=1 in the USART_SR register
	USART1->CR1 |= USART_CR1_RXNEIE;
 
	/* Set interrupt priority */
	NVIC_SetPriority(USART1_IRQn, 1);
 
	/* Enable interrupt */
	NVIC_EnableIRQ(USART1_IRQn);
 
	/* Enable receiver */
	USART1->CR1 |= USART_CR1_RE;
}
 
/* Transmit via USART */
void USART_Transmit(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size)
{
	/* For cycle to transmit byte by byte */
	for(uint16_t Index = 0; Index <= Size - 1; Index = Index + 1)
	{
		/* Wait until the data transmission register is empty */
		// This bit is set by HW when the content of the TDR register has been transmitted into the shift register. An interrupt is generated if the TXIE bit = 1 in the USART_CR1 register. It is cleared by a write to the USART_DR register
		while((USARTx->SR & USART_SR_TXE) == 0);
 
		/* Write data to be transmitted */
		USARTx->DR = *pData; // This clears the TXE bit
 
		/* Wait until transmission is complete */
		// TC bit is set by HW if the transmission of a frame containing data is complete and if TXE is set. An interrupt is generated if TCIE = 1 in the USART_CR1 register.
		while((USARTx->SR & USART_SR_TC) == 0);
 
		/* Pointer increase by 8 bits */
		pData = pData + 1;
	}
}
 
/* Receive via USART */
void USART_Receive(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size)
{
	/* Wait until the read data receive register is not empty */
	// When a character is received, the RXNE bit is set. It indicates that the content of the shift reister is transferred to the RDR. IN other words, data has been received and can be read (as well as its associated error flags)
	//while((USARTx->SR & USART_SR_RXNE) == 0);
 
	/* Read data received */
	*pData = USARTx->DR; // This clears the RXNE bit to the USART_DR register.
}
 
uint32_t Counter = 0;
void USART1_IRQHandler(void)
{
	Counter = Counter + 1;
}
 
/* Main */
int main(void)
{
	/* Initialize GPIO PA2 pin */
	GPIO_Init_PA2();
 
	/* Initialize USART USART2 module */
	USART_Init_USART2();
 
	/* Initialize GPIO PA10 pin */
	GPIO_Init_PA10();
 
	/* Initialize USART USART1 module */
	USART_Init_USART1();
 
	/* Buffer */
	char DataTx = 'A';
 
	/* Infinite loop */
	while(1)
	{
		/* Transmit via USART2 */
		USART_Transmit(USART2, (uint8_t *)&DataTx, 1);
	}
}

16 REPLIES 16
FGiai.1
Associate II

Yes, you are right. The various trials brought me to have a different code.

Here the modifications I did:

  1. I'm considering USART2 and USART3 which are on the same APB bus. In this way, I cannot have any issue related to the baude rate (they are for sure the same because are obtained from the same clock and calculated in the same way);
  2. Every time USART3 reads 10 the green LED is toggled.
  3. Added a delay between the sending of one uint8_t and the followng one (USART2);

In this case, again, no counter increase and no LED toggling.

Please, I have really no idea of how to continue... :(

#include "main.h"
 
/* Initialize GPIO PA2 pin */
void GPIO_Init_PA2(void)
{
	/* Enable IO port A clock */
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
 
	/* Configure the I/O direction mode */
	// 10: Alternate function mode
	GPIOA->MODER &= ~GPIO_MODER_MODE2_0;
	GPIOA->MODER |=  GPIO_MODER_MODE2_1;
 
	/* Configure the I/O alternate function */
	// 0111: AF7 (i.e. USART2_TX for GPIO PA2 pin)
	GPIOA->AFR[0] |=  GPIO_AFRL_AFRL2_0;
	GPIOA->AFR[0] |=  GPIO_AFRL_AFRL2_1;
	GPIOA->AFR[0] |=  GPIO_AFRL_AFRL2_2;
	GPIOA->AFR[0] &= ~GPIO_AFRL_AFRL2_3;
}
 
/* Initialize USART USART2 */
void USART_Init_USART2(void)
{
	/* Enable USART2 clock */
	RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
 
	/* Enable USART2 */
	USART2->CR1 |= USART_CR1_UE;
 
	/* Select the word length */
	// 0: 1 Start bit, 8 Data bits, n Stop bits
	USART2->CR1 &= ~USART_CR1_M;
 
	/* Select number of stop bits */
	// 00: 1 Stop Bit
	USART2->CR2 &= ~USART_CR2_STOP_0;
	USART2->CR2 &= ~USART_CR2_STOP_1;
 
	/* Select the baud rate */
	USART2->BRR = (8 << 4) | 10;
 
	/* Select parity */
	// 0: Even parity
	//USART2->CR1 &= ~USART_CR1_PS;
 
	/* Enable transmitter */
	USART2->CR1 |= USART_CR1_TE;
}
 
/* Initialize GPIO PC11 pin */
void GPIO_Init_PC11(void)
{
	/* Enable IO port C clock */
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
 
	/* Configure the I/O direction mode */
	// 10: Alternate function mode
	GPIOC->MODER &= ~GPIO_MODER_MODE11_0;
	GPIOC->MODER |=  GPIO_MODER_MODE11_1;
 
	/* Configure the I/O alternate function */
	// 0111: AF7 (i.e. USART1_RX for GPIO PC11 pin)
	GPIOC->AFR[1] |=  GPIO_AFRH_AFSEL11_0;
	GPIOC->AFR[1] |=  GPIO_AFRH_AFSEL11_1;
	GPIOC->AFR[1] |=  GPIO_AFRH_AFSEL11_2;
	GPIOC->AFR[1] &= ~GPIO_AFRH_AFSEL11_3;
}
 
/* Initialize USART USART3 */
void USART_Init_USART3(void)
{
	/* Enable USART3 clock */
	RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
 
	/* Enable USART3 */
	USART3->CR1 |= USART_CR1_UE;
 
	/* Select the word length */
	// 0: 1 Start bit, 8 Data bits, n Stop bits
	USART3->CR1 &= ~USART_CR1_M;
 
	/* Select number of stop bits */
	// 00: 1 Stop Bit
	USART3->CR2 &= ~USART_CR2_STOP_0;
	USART3->CR2 &= ~USART_CR2_STOP_1;
 
	/* Select the baud rate */
	USART3->BRR = (8 << 4) | 10;
 
	/* Select parity */
	// 0: Even parity
	//USART3->CR1 &= ~USART_CR1_PS;
 
	/* Enable RXNE interrupt */
	// 1: An USART interrupt is generated whenever ORE=1 or RXNE=1 in the USART_SR register
	USART3->CR1 |= USART_CR1_RXNEIE;
 
	/* Set interrupt priority */
	NVIC_SetPriority(USART3_IRQn, 1);
 
	/* Enable interrupt */
	NVIC_EnableIRQ(USART3_IRQn);
 
	/* Enable receiver */
	USART3->CR1 |= USART_CR1_RE;
}
 
/* Initialize GPIO PA5 pin */
void GPIO_Init_PA5(void)
{
	/* Enable IO port A clock  */
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
 
	/* Configure the I/O direction mode */
	// 01: General purpose output mode
	GPIOA->MODER |=  GPIO_MODER_MODE5_0;
	GPIOA->MODER &= ~GPIO_MODER_MODE5_1;
}
 
/* Toggle GPIO PA5 pin */
void GPIO_TogglePin_PA5()
{
	/* Toggle GPIO PA5 pin */
	GPIOA->ODR ^= GPIO_ODR_OD5;
}
 
/* Transmit via USART */
void USART_Transmit(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size)
{
	/* For cycle to transmit byte by byte */
	for(uint16_t Index = 0; Index <= Size - 1; Index = Index + 1)
	{
		/* Wait until the data transmission register is empty */
		// This bit is set by HW when the content of the TDR register has been transmitted into the shift register. An interrupt is generated if the TXIE bit = 1 in the USART_CR1 register. It is cleared by a write to the USART_DR register
		while((USARTx->SR & USART_SR_TXE) == 0);
 
		/* Write data to be transmitted */
		USARTx->DR = *pData; // This clears the TXE bit
 
		/* Wait until transmission is complete */
		// TC bit is set by HW if the transmission of a frame containing data is complete and if TXE is set. An interrupt is generated if TCIE = 1 in the USART_CR1 register.
		while((USARTx->SR & USART_SR_TC) == 0);
 
		/* Pointer increase by 8 bits */
		pData = pData + 1;
	}
}
 
/* Receive via USART */
//void USART_Receive(USART_TypeDef *USARTx, uint8_t *pData, uint16_t Size)
//{
//	/* Wait until the read data receive register is not empty */
//	// When a character is received, the RXNE bit is set. It indicates that the content of the shift reister is transferred to the RDR. IN other words, data has been received and can be read (as well as its associated error flags)
//	while((USARTx->SR & USART_SR_RXNE) == 0);
//
//	/* Read data received */
//	*pData = USARTx->DR; // This clears the RXNE bit to the USART_DR register.
//}
 
/* Global variables initialization */
volatile uint8_t DataRx;
volatile uint32_t Counter = 0;
 
/* USART3 IRQ handler */
void USART3_IRQHandler(void)
{
	/* Increase counter */
	Counter = Counter + 1;
 
	/* USART1 IRQ handler */
	if((USART3->SR & USART_SR_RXNE) != 0)
	{
 
		/* Read USART1 DR register */
		DataRx = USART3->DR;
 
		/* Toggle pin if the received data is equal to the transmitted */
		if(DataRx == 10)
		{
			GPIO_TogglePin_PA5();
		}
		/* Clear RXNE register */
		USART3->SR &= ~USART_SR_RXNE;
	}
}
 
/* Main */
int main(void)
{
	/* Initialize GPIO PA2 pin */
	GPIO_Init_PA2();
 
	/* Initialize USART USART2 module */
	USART_Init_USART2();
 
	/* Initialize GPIO PC11 pin */
	GPIO_Init_PC11();
 
	/* Initialize USART USART3 module */
	USART_Init_USART3();
 
	/* Initialize GPIO PA5 pin */
	GPIO_Init_PA5();
 
	/* Local variables initialization */
	uint8_t DataTx = 10;
 
	/* Infinite loop */
	while(1)
	{
		for(int k = 0; k <= 10000000; k++);
		USART_Transmit(USART2, (uint8_t *)&DataTx, 1);
	}
}

Pavel A.
Evangelist III

Likely you're suffering from receive overrun.

Disable the overrun detection and interrupt.

-- pa

> Disable the overrun detection and interrupt.

In the 'F4, there's no OVRDIS bit, so you MUST check and clear overrun.

And, don't RMW UART_SR, just write plain 0 where you need to, the bits in there are either read-only or rc_w0. Also, don't clear the RXNE bit - it is cleared by reading UART_DR and by explicitly clearing it you may accidentally clear indication of the next incoming byte.

JW

FGiai.1
Associate II
  • How can be overrun if I put a delay between a trasmission and the next one? In addition, in case of overrun the counter would increase because the SW would enter the IRQ handler.In this case, instead, it seems that the code does not enter in the handler for any reason. Do you see any issue that can avoid the software going in the usqrt IRQ handler?
  • Do you think these modifications can make the code working?

Thank you in Advance.​

  • ​How can be overrun if I put a delay between a trasmission and the next one? In addition, in case of overrun the counter would increase because the SW would enter the IRQ handler.In this case, instead, it seems that the code does not enter in the handler for any reason. Do you see any issue that can avoid the software going in the usqrt IRQ handler?
  • Do you think these modifications can make the code working?

Thank you in Advance.​

Pavel A.
Evangelist III

Ok I stand corrected about the overrun on 'F4.

If there's not a single interrupt from USART3 then maybe RX pin is obstructed. Time to get that logic analyser from the shelf.

Also make a sanity check that you receive any USART3 interrupt, for example enable TXE interrupt.

--pa

FGiai.1
Associate II

Hello all,

I discovered that USART2 Is connected by default to the st-link​, so It doesn't transmit anything by the PA2 pin if some soldering Is not done.

​​

Using the same code, but transmitting from UART4 instead of USART2 It works vert well.

Thank you all for the support.​