cancel
Showing results for 
Search instead for 
Did you mean: 

How to receive all data over UART interrupt?

Birdym
Associate II

I am using a STM32LO73RZ board. I have set up UART with interrupts and this works. I receive data that I send from an USB to TTL converter. When I sent a character one by one, this works fine. However, when I try to send a larger message, I keep missing a few characters. It starts after the first 4 bytes that are received. Does anybody know how to fix this?

1 ACCEPTED SOLUTION

Accepted Solutions

Hi @Birdym​ 

Your HAL_UART_RxCpltCallback() will apply for both UART handles (huart2 and huart5) (is it what it intended ?).

So, what I expect your code will do, is :

  • on each char received on COM on huart2 (stored in rx_buffer_uart2[0]), rx_buffer_uart5[0] is transmitted on huart2 . Reception on huart2 is re-started.
  • on each char received on COM on huart5 (stored in rx_buffer_uart5[0]), rx_buffer_uart5[0] is transmitted on huart2 . Reception on huart5 is re-started.

Is it really tour use case ?

Regarding loss of chars, as mentioned by @Ozone​ , reason might be that you spent too much time in RX interrupt handler.

When calling HAL_UART_Receive_IT(&huartx, rx_buffer_uartx, 1), on each char received a RXNE will be raised, as and expected length is 1, the reception will be considered as complete, and then callback will be executed in IT context.

Please note that HAL_UART_Transmit() is a "polling based" function : char will be transmitted, and function exits only when transmission is completed (this is detetced by polling flags in UART registers). So this function will at least last for a char transmission time. If another character is received during this period, IT will be delayed ...

So calling HAL_UART_Transmit() in your Rx complete callback is too time consuming.

Could you try to perform transmission also in Interrupt mode ? => using HAL_UART_Transmit_IT()

This will generate more interrupts, but depending of used baudrate, it could work ...

View solution in original post

7 REPLIES 7
Ozone
Lead

Almost certainly you are wasting too much time in interrupt context.

When you don't pull out the received character until the next arrives, it is overwritten, and the OV error is set.

Posting some code would be helpful.

I'm not a Cube user, BTW.

Birdym
Associate II
 /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_USART5_UART_Init();
 
  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_IT(&huart2, rx_buffer_uart2, 1);
  HAL_UART_Receive_IT(&huart5, rx_buffer_uart5, 1);
  /* USER CODE END 2 */
 
/* RX callback */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UART_Transmit(&huart2, rx_buffer_uart5, 1, 1000);
	HAL_UART_Receive_IT(huart, rx_buffer_uart5, 1);
}
/* RX callback */

At the first part the USART ports I am using are initialized, after this I call the receive with interrupt function, and after each byte is received, my code jumps to the callback function.

Birdym
Associate II
/* USER CODE BEGIN PV */
uint8_t rx_buffer_uart2[20];
uint8_t rx_buffer_uart5[20];
/* USER CODE END PV */

And here is my declaration of the used variables.

Birdym
Associate II

How can I pull out a received character and still be able to see what I have received?

Birdym
Associate II

This is an example of what happens when I transmit a message. COM 8 is mu USB to TTL and COM 4 is my STM32L073RZ board. As you can see, it skips the 5th character and the 10th.0693W000000UgrqQAC.png

Hi @Birdym​ 

Your HAL_UART_RxCpltCallback() will apply for both UART handles (huart2 and huart5) (is it what it intended ?).

So, what I expect your code will do, is :

  • on each char received on COM on huart2 (stored in rx_buffer_uart2[0]), rx_buffer_uart5[0] is transmitted on huart2 . Reception on huart2 is re-started.
  • on each char received on COM on huart5 (stored in rx_buffer_uart5[0]), rx_buffer_uart5[0] is transmitted on huart2 . Reception on huart5 is re-started.

Is it really tour use case ?

Regarding loss of chars, as mentioned by @Ozone​ , reason might be that you spent too much time in RX interrupt handler.

When calling HAL_UART_Receive_IT(&huartx, rx_buffer_uartx, 1), on each char received a RXNE will be raised, as and expected length is 1, the reception will be considered as complete, and then callback will be executed in IT context.

Please note that HAL_UART_Transmit() is a "polling based" function : char will be transmitted, and function exits only when transmission is completed (this is detetced by polling flags in UART registers). So this function will at least last for a char transmission time. If another character is received during this period, IT will be delayed ...

So calling HAL_UART_Transmit() in your Rx complete callback is too time consuming.

Could you try to perform transmission also in Interrupt mode ? => using HAL_UART_Transmit_IT()

This will generate more interrupts, but depending of used baudrate, it could work ...

I have adjusted the size of the data message to be expected and this worked for me, but thank you for replying! @Ozone​ @Guenael Cadier​