cancel
Showing results for 
Search instead for 
Did you mean: 

How to receive a whole string of characters, sent by a computer to a NUCLEO-L432KC using UART communication?

Loic1
Associate III

Hello everyone,

I would like to transmit strings of characters (which could be different sizes) using the Nucleo's UART serial communication. I'm using HAL_UART_Receive_IT(&huart2, &rx_buffer, 1), which receives the characters one by one and stores them into my rx_buffer, replacing the previous one.

If I increase the amount of data elements to be received, the smaller strings of characters will not be enough to fulfill the expected amount of data elements to be received, and the HAL_UART_RxCpltCallback() will not be triggered.

Is there a way to get the whole string of character, or to know if the the communication has ended, like a timeout flag?

Thanks in advance!

Loïc

1 ACCEPTED SOLUTION

Accepted Solutions
Muhammed Güler
Senior II

I suggest to use USART with DMA and idle line detection.

below is an example

0693W00000NphwRQAR.png

uint8_t  RxBuffer[256],RxLenght;
// in init
HAL_UART_Receive_DMA(&huart3,RxBuffer,255);
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
 
 
/**
in it file
*/
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
	if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))
	{
		HAL_UART_DMAStop(&huart3);
		//Calculate the length of the received data
		RxLenght= 255 - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
		//Restart to start DMA transmission of 255 bytes of data at a time
		HAL_UART_Receive_DMA(&huart3, (uint8_t*)RxBuffer, 255);
	}
  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
	
  /* USER CODE END USART3_IRQn 1 */
}

View solution in original post

11 REPLIES 11

With strings, people frequently use end-of-line indicators like <CR><LF>, ie "\r\n", or some combo thereof.

One could also time-stamp the character reception,and process the time-out elsewhere to take the line. Works less well for human interaction as they are slow and unpredictable.

Check if the L4 has some "LINE IDLE" type interrupt.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Muhammed Güler
Senior II

I suggest to use USART with DMA and idle line detection.

below is an example

0693W00000NphwRQAR.png

uint8_t  RxBuffer[256],RxLenght;
// in init
HAL_UART_Receive_DMA(&huart3,RxBuffer,255);
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
 
 
/**
in it file
*/
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
	if(__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE))
	{
		HAL_UART_DMAStop(&huart3);
		//Calculate the length of the received data
		RxLenght= 255 - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
		//Restart to start DMA transmission of 255 bytes of data at a time
		HAL_UART_Receive_DMA(&huart3, (uint8_t*)RxBuffer, 255);
	}
  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
	
  /* USER CODE END USART3_IRQn 1 */
}

Loic1
Associate III

Hi @Community member​ !

Thank you for your fast answer. I'm looking how to do this and trying to do it by myself. I'll reply back for learning more if I have any issue.

Loïc

Hi @Muhammed G�ler​ !

Thanks for the screenshot and code, seems pretty simply and efficient. I'll give it a try and let you know about it.

Loïc

Hi @Tesla DeLorean (Community Member)​ !

Thank you for your fast answer. I'm looking how to do this and trying to do it by myself. I'll reply back for learning more if I have any issue.

Loïc

Hi again!

I'm trying to detect the '\r' character at the end of the sent string, but when sending a string via the STM32CubeIDE built-in serial monitor in debugging mode, I get a strange behavior. See in the screenshot below, sometimes there is the '\r' at the end of the string (when I first sent "CMD" and hit Enter), sometimes not (then I sent "kCMD").

0693W00000NpkdhQAB.pngHow could I manage to get the '\r' every time when I send a string?

Loïc

Hi again @Muhammed G�ler​ !

I'm trying the DMA method with the UART communication. There's no USART3 on the Nucleo-L432KC so I'm using the USART2.

With your code, I'm having a strange behavior. Indeed, the USART2_IRQHandler() is constantly triggered, even if I'm not sending anything through the serial monitor.

What's the issue here?

To reply to my previous question, I figured out that the USART2_IRQHandler() is constantly triggered because of the __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE). It sets an interrupt that's triggered when IDLEFLAG is set (when there is no UART communication).

To make the interrupt happen only once, I clear the IDLEFLAG using __HAL_UART_CLEAR_IDLEFLAG(&huart2) in the USART2_IRQHandler().

Also, I don't want to trigger the USART2_IRQHandler() at my program's beginning. The IDLEFLAG is firstly set at the MX_USART2_UART_Init(), so I've put my __HAL_UART_CLEAR_IDLEFLAG(&huart2) just after it.

My issue there is the following: in debugging mode, the IDLEFLAG reset works if I run the lines one by one, but seems to be skipped if I don't make a stop on the line.

How to be sure to reset the IDLEFLAG in normal run?

Loïc

The HAL_UART_IRQHandler function needs to contain the __HAL_UART_CLEAR_IDLEFLAG macro. (at least it's in the F4 library)

If you increase the value of a variable where you stop and start DMA, you can see if the number of incoming packets matches the number of times the interrupt function runs.