Skip to main content
smrtkai
Associate III
April 5, 2016
Question

Continous data reception using USART

  • April 5, 2016
  • 4 replies
  • 1025 views
Posted on April 05, 2016 at 16:52

Hi,

I would like to continously receive data via usart. I have a receive buffer configured to receive 1000 bytes in circular mode.

Now I would like to pause the dma, process the received data and resume the dma. How do I know how much bytes were received?

Thanks for your help in advance.
    This topic has been closed for replies.

    4 replies

    stm322399
    Senior
    April 5, 2016
    Posted on April 05, 2016 at 17:14

    Stoping the DMA is not advised when you want to receive a continuous stream.

    Assuming you are using an F4, the best option is to keep circular mode and enable HT and TC interrupts, so you will receive an interrupt every 500 bytes, that you can process while still receiving 500 others.

    If you can't wait for the interrupt (end of transfer, pause, etc ...) reading the NDTR register  of the concerned channel tell you remaining bytes to be received, from which you deduce the number of received bytes.

    smrtkai
    smrtkaiAuthor
    Associate III
    April 6, 2016
    Posted on April 06, 2016 at 10:20

    Thank you very much.

    I will try to read the NDTR register. That's what I was looking for.
    smrtkai
    smrtkaiAuthor
    Associate III
    April 6, 2016
    Posted on April 06, 2016 at 11:12

    I have figured out how to read the NDTR registers for my dma stream. In my setup I simply want to read the data from USART and process it. For test purposes I just want to output the received charaters. But unfortunately the received data is not (completely) in the buffer. Even when I wait for sometime.

    This is my test code:

    char rx_buf[1000];

    HAL_UART_Receive_DMA(&huart5, (uint8_t*) rx_buf, 1000);

    uint32_t prev_ntdr = 1000;

    uint32_t rcvd_bytes = 0;

    uint32_t read_idx = 0;

    while (1) {

        // determine number of received bytes

        HAL_UART_DMAPause(&huart5);

        rcvd_bytes = prev_ntdr - huart5.hdmarx->Instance->NDTR;

        prev_ntdr = huart5.hdmarx->Instance->NDTR;

        HAL_UART_DMAResume(&huart5);

        

        HAL_Delay(500);

        

        // process received bytes

        printf(''received %d bytes\n'', rcvd_bytes);

        for (uint32_t i = 0; i < rcvd_bytes; i++) {

          printf(''%c'', rx_buf[read_idx]);

          read_idx++;

        }

        printf(''\n'');

        

        HAL_Delay(500);

    }

    My DMA configuration looks like this:

        hdma_uart5_rx.Instance = DMA1_Stream0;

        hdma_uart5_rx.Init.Channel = DMA_CHANNEL_4;

        hdma_uart5_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;

        hdma_uart5_rx.Init.PeriphInc = DMA_PINC_DISABLE;

        hdma_uart5_rx.Init.MemInc = DMA_MINC_ENABLE;

        hdma_uart5_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

        hdma_uart5_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

        hdma_uart5_rx.Init.Mode = DMA_CIRCULAR;

        hdma_uart5_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;

        hdma_uart5_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;

        hdma_uart5_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

        hdma_uart5_rx.Init.MemBurst = DMA_MBURST_SINGLE;

        hdma_uart5_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;

        HAL_DMA_Init(&hdma_uart5_rx);

    smrtkai
    smrtkaiAuthor
    Associate III
    April 7, 2016
    Posted on April 07, 2016 at 10:54

    The size of the FIFO and its threshold were too high for my application. After turning of the FIFO all data was available as expected.

    Stupid mistake.