Skip to main content
gaetanbusson
Associate II
April 17, 2018
Solved

RS485 frame reception through DMA and UART

  • April 17, 2018
  • 6 replies
  • 2611 views
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?

    This topic has been closed for replies.
    Best answer by AvaTar
    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.

    6 replies

    AvaTar
    Senior III
    April 17, 2018
    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.

    gaetanbusson
    Associate II
    May 9, 2018
    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

    T J
    Senior III
    May 9, 2018
    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);
     }
    }
    
    �?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?