multiple string transmit over USART using CubeMx

9.9k views Asked by At

I was trying USART using a STM32F407VGT6 and CubeMX.

I am able to send and receive data using Interrupts. But I am getting a problem which I am not able to understand:

I am using HAL_UART_Transmit_IT to send the data.
I have enabled __HAL_UART_ENABLE_IT(&huart3,UART_IT_TC);.

Here is my code:

int main(void)
{
  HAL_Init();
  MX_GPIO_Init();
  MX_USART3_UART_Init();
  Green_Blink(100);
  Orange_Blink(100);
  Blue_Blink(100);
  Red_Blink(100);
  HAL_Delay(100);

  __HAL_UART_ENABLE_IT(&huart3,UART_IT_TC);
  char buff[] = {'2','4','.','0','0'};
  while (1)
  {
        HAL_UART_Transmit_IT(&huart3,(uint8_t*)"OK\r\n ",5);
        HAL_UART_Transmit_IT(&huart3,(uint8_t*)buff,5);
        HAL_UART_Transmit_IT(&huart3,(uint8_t*)"OK\r\n ",5);
        HAL_UART_Transmit_IT(&huart3,(uint8_t*)buff,5);
        HAL_UART_Transmit_IT(&huart3,(uint8_t*)"OK\r\n ",5);
        HAL_UART_Transmit_IT(&huart3,(uint8_t*)buff,5);
        HAL_Delay(1000);
        Blue_Blink(100);

  }
}

So I am sending this kind of data. First, I am sending OK and then I am sending the buffer data as you can see.

But in terminal(tera term in my case) I can't see the buffer data.
I can see OK.

I don't know why this is happening. And how to resolve it?
Any suggestions?

3

There are 3 answers

9
0___________ On BEST ANSWER

You need to wait for the callback, which indicates the end of transmission . It is the interrupt function which is executed asynchronously. It does not have a chance to send even a single byte.

You just override the buffer and start the transmission over.

For this kind of messages, use blocking functions. Use DMA or interrupt ones when your main program is doing something during the communication, and you want the communication to be done in the background.

Edit

Some explanation. HAL interrupt functions do not wait until the transmission is completed. They return immediately to the caller and the communication is completed in the background. The main program can execute in parallel doing another tasks. When all bytes are sent (or on error) HAL library invokes the appropriate callback. For end of transmission it is: void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)

Because of the asynchronous execution if you want to start another transmission you need to know if the previous one has already completed.

Edit 2

In this case it does not make any sense to send asynchronously. You need to wait for the end of the previous transmissions:

volatile int USART3TransferCompleted;

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    USART3TransferCompleted = 1; // this functions should check the instance as well
}

and in main function:

        USART3TransferCompleted = 0;
        HAL_UART_Transmit_IT(&huart3,(uint8_t*)"OK\r\n ",5);
        while(!USART3TransferCompleted);
        USART3TransferCompleted = 0;
        HAL_UART_Transmit_IT(&huart3,(uint8_t*)buff,5);
        while(!USART3TransferCompleted);
        ...
2
RTOS On

I created my account just to say thanks to P__J__.

I struggled to send multiple HAL_UART_Transmit_IT in a row as below.

HAL_UART_Transmit_IT(&huart1,(uint8_t*) Test_Buffer1, length1); HAL_Delay (1000); HAL_UART_Transmit_IT(&huart1,(uint8_t*) Test_Buffer2, length2);

P__J__ solution above by using HAL_UART_TxCpltCallback to wait for the end of the previous transmissions WORKS perfectly.

0
ufo On
if(HAL_UART_Transmit(&huart2, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 5000)!= HAL_OK)
    {
      Error_Handler();
    }

use this HAL function without callback interrupt.