Skip to main content
GGeor.4
Associate II
August 16, 2018
Question

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

  • August 16, 2018
  • 5 replies
  • 1382 views

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?

This topic has been closed for replies.

5 replies

Tesla DeLorean
Guru
August 16, 2018

>>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 VenmoUp vote any posts that you find helpful, it shows what's working..
GGeor.4
GGeor.4Author
Associate II
August 16, 2018

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
GGeor.4Author
Associate II
August 16, 2018

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
Senior III
August 17, 2018

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
Senior III
August 17, 2018

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"); 
}