cancel
Showing results for 
Search instead for 
Did you mean: 

RS485 frame reception through DMA and UART

gaetanbusson
Associate II
Posted on April 17, 2018 at 15:34

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?

1 ACCEPTED SOLUTION

Accepted Solutions
Posted on May 09, 2018 at 14:20

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.

View solution in original post

6 REPLIES 6
AvaTar
Lead
Posted on April 17, 2018 at 16:05

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.

Posted on May 09, 2018 at 13:54

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

Posted on May 09, 2018 at 14:01

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

�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Posted on May 09, 2018 at 14:20

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.

Posted on May 09, 2018 at 14:54

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)

Posted on May 09, 2018 at 15:18

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.