cancel
Showing results for 
Search instead for 
Did you mean: 

Continous data reception using USART

smrtkai
Senior
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.
4 REPLIES 4
stm322399
Senior
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
Senior
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
Senior
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
Senior
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.