2018-04-17 06:34 AM
Hello
I am starting a new project in which I have to use a RS4785 communication and this time, I'd like to do it well.
The problem is the following:
If I want to receive a frame with UART using DMA, I need to call HAL_UART_Receive_DMA function. This function needs to have the 'size' parameter to know the amount of data to be received. Unfortunately, the size of data being received is unknown.
The protocol I am using is MODBUS and it assumes that an end of frame can be detected is there is a silence time (three times the delay of 1 byte) detected.
My question is the following: how can I automatically stop the reception process when this silence time is detected so that my HAL_UART_RxCpltCallback callback can be called? Is there any flow control function I can use with UART to control the DMA?
Solved! Go to Solution.
2018-05-09 07:20 AM
I've had a look at the datasheet for this MCU but unfortunately, I haven't found such functionality.
Receiver Timeout Register, USART_RTOR , (including a Receiver Timeout Interrupt).
In the F030x8 supported for USART1.
2018-04-17 07:05 AM
Which MCU you want/need to work with ?
I worked with a F0 a while ago that supported an idle timeout for the UART, which would be almost perfect for a Modbus RT implementation.
But I would be really surprised if Cube supported this feature properly.
And, if I remember correctly, 38600 is the maximal specified baudrate for serial Modbus.
I would consider an interrupt-based send/receive, especially in regard to possible reception errors.
2018-05-09 06:54 AM
Hi!
Thank you for responding. The MCU I am using is STM32f030R8T.
I've had a look at the datasheet for this MCU but unfortunately, I haven't found such functionality.
9600 bauds will be enought for my application
2018-05-09 07:01 AM
the DMA size parameter is the circular buffer size.
I use this to check the size:
char readableU1(void) {
U1RxBufferPtrIN = U1RxBufSize - huart1.hdmarx->Instance->CNDTR;
return U1RxBufferPtrIN - U1RxBufferPtrOUT;
}
char readU1(void) {
char readByte = Usart1RxDMABuffer[U1RxBufferPtrOUT++];
if (U1RxBufferPtrOUT >= U1RxBufSize) U1RxBufferPtrOUT = 0;
return readByte;
}
char getc1(void) {
char Rxbyte = Usart1RxDMABuffer[U1RxBufferPtrOUT++];
if (U1RxBufferPtrOUT >= U1RxBufSize) U1RxBufferPtrOUT = 0;
return Rxbyte;
}
Init:
void initUart1RxDMABuffer(void) {
if (HAL_UART_Receive_DMA(&huart1, (uint8_t *)Usart1RxDMABuffer, U1RxBufSize) != HAL_OK)
{
// Transfer error in reception process
//_Error_Handler(__FILE__, __LINE__);
char string[32];
sprintf(string, 'initUart1RxDMABuffer Failed
');
puts1(string);
}
else
{
char string[32];
sprintf(string, 'initUart1RxDMABuffer OK!
');
puts1(string);
}
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-05-09 07:20 AM
I've had a look at the datasheet for this MCU but unfortunately, I haven't found such functionality.
Receiver Timeout Register, USART_RTOR , (including a Receiver Timeout Interrupt).
In the F030x8 supported for USART1.
2018-05-09 07:54 AM
you are right! I've missed it!
This is bad luck for me: the functionnality is not available for the UART I have to use (USART2)
2018-05-09 08:18 AM
The monitoring of the idle times is crucial for Modbus-RT, I would consider swapping USARTs (i.e. USART1 for Modbus).
Another (awkward) option would perhaps be connecting another pin to RX, and monitor the timing via EXTI and/or timer peripheral.