Skip to main content
Visitor II
December 15, 2024
Question

External ADC Sampling with DMA (Timing & Configuration)

  • December 15, 2024
  • 3 replies
  • 1374 views

 

Hi everyone,

I’m working on a project using an STM32 microcontroller (STM32H745IITx), and I’m trying to set up a DMA transfer for an external 12-bit, 20 MSPS ADC with a 12-bit parallel interface. On my custom board, the data pins of the ADC are routed to the GPIOF port. The ADC clock is generated using Timer 3's PWM output (running at approximately 18 MHz). Additionally, I have an external interrupt (Trigger) that I use to start a measurement.

I want to achieve the following:

  1. The external interrupt should start the DMA transfer.
  2. The DMA should then transfer the GPIOF port data on every Timer 3 interrupt event.

I’ve done some research and found that the DMA must be set to Memory-to-Memory mode to achieve this. However, it’s not clear to me:

  • When I call HAL_DMA_Start_IT, does the DMA transfer the entire buffer at the specified DMA speed?
  • Or, is there a way to link the DMA transfer to Timer 3, so that the DMA reads the GPIO port on every Timer 3 interrupt?

Any help or clarification would be greatly appreciated


 

 

 

    This topic has been closed for replies.

    3 replies

    Super User
    December 15, 2024

    Since you want the transfer to happen in response to a trigger, the DMA should be in peripheral-to-memory mode. Then, if the correct trigger happens (presumably TIM3_TRGO or similar), it will transfer.

    In memory-to-memory mode there are no triggers--the entire buffer will transfer as fast as possible once it is started.

    It may be difficult to set this up in STM32CubeMX but the hardware can certainly support it given the correct setup.

    ZIMMI99Author
    Visitor II
    December 16, 2024

    Thank you for the informations,

    I have now tried to trigger the DMA over the EXTI0 Interrupt Callback: 

    void EXTI0_IRQHandler(void)
    {
     HAL_NVIC_DisableIRQ(EXTI0_IRQn);
     /* USER CODE BEGIN EXTI0_IRQn 0 */
     HAL_DMA_Start_IT(&hdma_tim3_up, (uint32_t)&GPIOF->IDR, (uint32_t)scope_buf, scope_buf_len);
     /* USER CODE END EXTI0_IRQn 0 */
     HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
     /* USER CODE BEGIN EXTI0_IRQn 1 */
    
     /* USER CODE END EXTI0_IRQn 1 */
    }

    I would expect that the signal is now always sampled at the same time by the dma. However, the start of the measurement is always different to the trigger signal at EXTI0. I know that interrupts have a long delay, but the delay should always be the same size Am I missing something?

    For information I sample a periodic signal which generates a periodic pulse through an external comparator. This leads to the EXTI0. After the interrupt is firing, i disable the interrupt and process the data. After the processing is finished i enable the interrupt again.

    Super User
    December 18, 2024

    Hard to answer without the details. A 20 Msps ADC is probably going to require some tight timing. What do you require in terms of the EXTI0 edge and sampling times? What are you seeing instead? Details. Logic analyzer plot is possible.

    > However, the start of the measurement is always different to the trigger signal at EXTI0.

    How are you measuring this? What measurements are you seeing?

    If you take out the EXTI0 part, is GPIOF getting sampled at the expected rate? Work in steps.