cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_TxCpltCallback Issue at Higher Buadrate

JThom.15
Associate III

Hi all,

I am using UART4 in STM32F205 connected to an external device with an RS485-Transceiver (sn65hvd75).When I transmit data (HAL_UART_Transmit_IT) I set the TXEN pin high in RS485-Transceiver and when I get a callback  using HAL_UART_TxCpltCallback, I reset the TXEN pin to receive the data, It works fine in lower baudrates(9600), but at higher baudrate(115200) the response from external device gets corrupted because the TXEN has not been resetted before we start receiving data.

Does anyone know whether there is delay in HAL_UART_TxCpltCallback or is there any other way to make sure the transmit is complete (to reset the TXEN pin)?

1 ACCEPTED SOLUTION

Accepted Solutions

Try calling _txen->set_low (or simply write directly to gpio register GPIOx->BSRR) in the TxCpltCallback. Also you could try using Task Notifications instead of Events as it will execute faster.

View solution in original post

9 REPLIES 9
Sarra.S
ST Employee

Hello @JThom.15

If you're not already using DMA for UART transmission, consider using it, it can help with reducing the delay with less CPU intervention. 

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

TDK
Guru

HAL_UART_TxCpltCallback is not called instantly, but it will be called fairly quickly. What timing requirement do you have here?

I'd suggest calling HAL_UART_Receive_IT prior to the transmission being complete so that you're ready to receive data when it happens. It doesn't seem like the TXEN signal should be affecting received bytes.

If you feel a post has answered your question, please click "Accept as Solution".

@TDK Thanks for the reply

I use the HAL_UART_TxCpltCallback to set the TXEN low. 

I used the scope and it seems like TXEN held high little bit longer even after the transmit is finished and recieve msgs are not getting through.

 

> I used the scope and it seems like TXEN held high little bit longer even after the transmit is finished and recieve msgs are not getting through.

Do you think the two are connected? And if so why?

We don't know what "recieve msgs are not getting through" means in particular. Perhaps explain the symptoms in more detail. What debugging have you done? Does anything get through, if so what? What does your reception code look like?

If you feel a post has answered your question, please click "Accept as Solution".
mbrossett
Associate III

What clock frequency are you running? Below is a link to an ST app note on managing the driver enable pin for RS-485 applications. They provide timing measurements for an STM32F10x and it meets the requirements for 230,400 baud at 72MHz and 24MHz clock frequencies. You should have no problem at 115,200 baud. 

https://www.st.com/resource/en/application_note/an3070-managing-the-driver-enable-signal-for-rs485-and-iolink-communications-with-the-stm32s-usart-stmicroelectronics.pdf 

Please provide terminating resistors . How many slaves are there. Use twisted pair, reflections at higher baudrate is possible.  There are intelligent rs485 which automatically switch to rx mode. The other device can't start transmit before it receives full command, is it not?

So what you see on the line may be reflection.  You can connect another receiver and monitor. 

If you feel a post has answered your question, please click "Accept as Solution".

@TDK Most of the messages sent by the external devices are getting corrupted. Here is how we transmit and receive messages

Transmit Function

void UART::tx(const uint8_t* to_send, size_t length)
{  
   //Set TXEN pin High
    if (_txen.has_value())
    {
        _txen->set_high();
    }
        _error_encountered = false;
        auto status = HAL_UART_Transmit_IT(_uart, const_cast<uint8_t*>(to_send), length);
        if(status != HAL_OK)
        {
            HAL_UART_AbortTransmit_IT(_uart);
            if (_txen.has_value())
            {
                _txen->set_low();
            }
            return;
        }
        
        //Wait for Tranmit to complete
        xEventGroupWaitBits(_tx_done, BIT_TX_DONE, BIT_TX_DONE, true, portMAX_DELAY);
        if (_txen.has_value())
        {
            _txen->set_low();
        }
}

extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart)
{
    auto handle = lookup_handle(huart);
    if (handle == nullptr)
    {
        return;
    }
    handle->_error_encountered = false;
    xEventGroupSetBitsFromISR(handle->_tx_done, BIT_TX_DONE, nullptr);
}


 After we call the TX function we use HAL_UARTEx_ReceiveToIdle_IT to receive the msg

Try calling _txen->set_low (or simply write directly to gpio register GPIOx->BSRR) in the TxCpltCallback. Also you could try using Task Notifications instead of Events as it will execute faster.

@mbrossett Thanks for the response. T

hat fixed issue, xEventGroupWaitBits had a delay