cancel
Showing results for 
Search instead for 
Did you mean: 

RS-485: HAL_UART_Receive_IT() causes HAL_UART_RxCpltCallback() firing without any data to receive on the line

GGeor.4
Associate II

I'm transmitting 1 byte of data via HAL_UART_Transmit_IT(). After this byte is being fed to the UART HAL via the abovementioned method, the HAL_UART_TxCpltCallback() callback is being fired (which is completely normal). The problem comes during the consequent operation - I want to try to receive 1 byte of data via HAL_UART_Receive_IT(). After calling HAL_UART_Receive_IT() I don't expect firing the HAL_UART_RxCpltCallback() callback, because the serial port is totally disconnected and there's no way data to be present on it's RX line. But this is what actually happens - the HAL_UART_RxCpltCallback() is being called without any reason. And there is no error detected if I check the same UART's state by HAL_UART_GetError() in HAL_UART_RxCpltCallback() callback.

Any ideas what may cause this very strange behavior?

5 REPLIES 5

>>Any ideas what may cause this very strange behavior?

Are you inspecting the UART registers in the debugger?

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
GGeor.4
Associate II

It happens no matter if I inspect the HAL flow and the registers or not. If I put just a single breakpoint in the reception callback (HAL_UART_RxCpltCallback()) I see it being called, even so there's totally no data on the RX line (explicitly checked this line with oscilloscope as well).

GGeor.4
Associate II

Disabling UART_IT_RXNE before HAL_UART_Transmit_IT() and reenabling it after some explicit delay in HAL_UART_TxCpltCallback() workarounded the problem. I guess HAL ISR support is not coded by the greatest genius in the world.... Indeed, I plan to avoid using HAL from now on.

T J
Lead

did you read out the RxFifos before you enabled the interrupt ?

much better to use the DMAs

if you want the best solution for an interrupt for each char,

set the DMA circular buffer to 2 bytes,

you will get both halfFull and Full Callbacks

T J
Lead

but the easiest way toi use the Uarts is with DMA buffer set to 256bytes or more (1k), giving you time to get there...

you can easily check if a single byte has arrived:

U1RxBufferPtrIN =  U1RxBufSize - huart1.hdmarx->Instance->CNDTR; //next byte received will go here 
 
....
 
char readByte = Usart1RxDMABuffer[U1RxBufferPtrOUT++];
 
...
#define U1RxBufSize 256
#define U1TxBufSize 4096    
char Usart1TxDMABuffer[U1TxBufSize];
char Usart1RxDMABuffer[U1RxBufSize];
int16_t U1RxBufferPtrIN, U1RxBufferPtrOUT, U1TxBufferPtrIN, U1TxBufferPtrOUT;
char   TxDMA1BufHasData, DMA1BufAlmostFull;
 
 
 
void initUart1RxDMABuffer(void) {
    if (HAL_UART_Receive_DMA(&huart1, (uint8_t *)Usart1RxDMABuffer, U1RxBufSize) != HAL_OK)
        // Transfer error in reception process  
        printf"initUart1RxDMABuffer Failed\n");               
    else
        printf( "initUart1RxDMABuffer OK!\n");       
}