Skip to main content
Loic1
Associate II
May 10, 2022
Solved

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

  • May 10, 2022
  • 11 replies
  • 5332 views

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

This topic has been closed for replies.
Best answer by Muhammed Güler

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 */
}

11 replies

Tesla DeLorean
Guru
May 10, 2022

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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
Loic1
Loic1Author
Associate II
May 10, 2022

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

Muhammed Güler
Muhammed GülerBest answer
Senior III
May 10, 2022

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
Loic1Author
Associate II
May 10, 2022

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

Loic1
Loic1Author
Associate II
May 10, 2022

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

Loic1
Loic1Author
Associate II
May 23, 2022

So I managed to make a UART receiver that handles whole strings of characters at once, using DMA.  If you want to take a look at it to see if I was supposed to do it this way, or if something could be improved, you can find my main.c attached, and the rest of the code below. Any return will be appreciated.

In the main.h:

#include <string.h>
#define rx_buffer_size 255

In the stm32l4xx_it.c:

void USART2_IRQHandler(void)
{
 /* USER CODE BEGIN USART2_IRQn 0 */
 
	if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) // if the interruption is triggered by the idle flag
	{
		HAL_UART_DMAStop(&huart2); // stop UART DMA communication
 
		rx_length = rx_buffer_size - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx); // Calculate the length of the received data
		memcpy(rx_cmd, rx_buffer, rx_buffer_size); // copy the rx_buffer to the rx_cmd
		bzero(rx_buffer, rx_buffer_size); // empty the rx_buffer
		HAL_UART_Transmit_DMA(&huart2, rx_cmd, rx_buffer_size); // send the received string back
 
		HAL_UART_Receive_DMA(&huart2, (uint8_t*)rx_buffer, rx_buffer_size); // Re-enable DMA reception
	}
	__HAL_UART_CLEAR_IDLEFLAG(&huart2);
 
 /* USER CODE END USART2_IRQn 0 */
 HAL_UART_IRQHandler(&huart2);
 /* USER CODE BEGIN USART2_IRQn 1 */
 
 /* USER CODE END USART2_IRQn 1 */
}

Best regards,

Loïc