2

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?

Ehsan Habib
  • 135
  • 1
  • 5
  • 12

3 Answers3

3

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);
        ...
Community
  • 1
  • 1
0___________
  • 60,014
  • 4
  • 34
  • 74
  • I didn't actually get you. I am using interrupt for transmitting, what is callback how do i implement it? What is blocking functions? If i am using interrupts then isn't my communication is happening in the background? – Ehsan Habib Aug 16 '18 at 07:14
  • @EhsanHabib the general rule is: do not use something if you do not understand it. Give me a clue why interrupt? What did you want to archive? – 0___________ Aug 16 '18 at 07:30
  • @EhsanHabib use normal blocking function. Not IT or DMA ones and you will get what you want – 0___________ Aug 16 '18 at 07:31
  • @EhsanHabib Imagine that you are company drier. Your boss (main program) tells you to go to the airport to pick up someone. When you start the engine the same boss calls you and tells to go to the warehouse and deliver something. After another minuted he says you to pick up his children from the school and after another minuet to go to the shop and him some cigarettes. When you bring the cigarettes you get fired bacause you did not go to the airport, you did not deliver, and you did not pick-up his children. And only because he did not wait until you completed the particular tasks – 0___________ Aug 16 '18 at 07:51
  • okay i get it. So before sending another string i need to wait till the last string is completely sent. Should i wait like this `while (HAL_UART_Transmit_IT(&huart3,(uint8_t*)buff,6) == HAL_BUSY) wait++;` or is there any flag i should be waiting for? – Ehsan Habib Aug 16 '18 at 08:00
  • Ok i didn't see the edit. Let me try this. I will let you know the results – Ehsan Habib Aug 16 '18 at 08:02
  • I got confused while implementing `HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)` instead i just waited till `HAL_UART_Transmit_IT()` is busy. But i guess it's similar to the blocking function. Though things are working, if possible i would like to know how to implement `HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)`. – Ehsan Habib Aug 16 '18 at 08:41
  • I know that after going to uart irq the call will go to this `HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)` function. So should i just write `HAL_UART_Transmit_IT()` inside callback method? I don't know what should i do. – Ehsan Habib Aug 16 '18 at 08:43
  • No! forget the IT functions in this case in the callback you need to set the flag and poll for this flag your code. It is nonsense in this case – 0___________ Aug 16 '18 at 08:45
0
if(HAL_UART_Transmit(&huart2, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 5000)!= HAL_OK)
    {
      Error_Handler();
    }

use this HAL function without callback interrupt.

ufo
  • 1
0

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.

RTOS
  • 1
  • 2
    Please use comments to thank others or ask more details :) – Pierre Oct 16 '20 at 14:13
  • I also created an account to thanks 0___________ , solution above by using HAL_UART_TxCpltCallback as mention on "Edit 2" to wait for the end of the previous transmissions WORKS perfectly. – RTOS Apr 13 '21 at 12:46