2025-04-16 2:14 AM - last edited on 2025-04-16 6:29 AM by mƎALLEm
Hi,
I'm trying to connect a high speed ADC to an STM32F7. I have chained two timers to generate the necessary convert and read pulses to the ADC. Its output is 16 bits that are all connected to the same gpio block.
However I would also like to setup a DMA (double buffered) transfer from GPIO input register to memory that is timed from the timer.
The timer that generates the samples from the ADC to the gpio input is configured as a one shot timer with an output channel, in this case TIM1_CH1.
Config for the timer is:
m_rd_timer.Instance = TIM1;
m_rd_timer.Init.Prescaler = prescaler;
m_rd_timer.Init.CounterMode = TIM_COUNTERMODE_UP;
m_rd_timer.Init.Period = period_len;
m_rd_timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
m_rd_timer.Init.RepetitionCounter = 8-1;
m_rd_timer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
ocConfig.OCMode = TIM_OCMODE_PWM2;
ocConfig.Pulse = pulse_len;
ocConfig.OCPolarity = TIM_OCPOLARITY_LOW;
ocConfig.OCNPolarity = TIM_OCNPOLARITY_LOW;
ocConfig.OCIdleState = TIM_OCIDLESTATE_SET;
ocConfig.OCNIdleState = TIM_OCNIDLESTATE_SET;
ocConfig.ICPolarity = TIM_ICPOLARITY_FALLING;
ocConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
So basically every time the timer triggers it will generate a 8 active low pulses of a certain pulse length.
From a timing perspective the falling edge of the timer output will tell the ADC to output data to GPIO block and rising edge would be the time to actually read the GPIO register.
How do I setup the timer + DMA to do this?
DMA_HandleTypeDef dma2_stream0 = {0};
dma2_stream0.Instance = DMA2_Stream0;
dma2_stream0.Init.Channel = DMA_CHANNEL_6; // DMA2 Channel 6, stream 0 => TIM1_TRIG
dma2_stream0.Init.Direction = DMA_PERIPH_TO_MEMORY;
dma2_stream0.Init.PeriphInc = DMA_PINC_DISABLE;
dma2_stream0.Init.MemInc = DMA_MINC_ENABLE;
dma2_stream0.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
dma2_stream0.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
dma2_stream0.Init.Mode = DMA_NORMAL;
dma2_stream0.Init.Priority = DMA_PRIORITY_HIGH;
dma2_stream0.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
dma2_stream0.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
dma2_stream0.Init.MemBurst = DMA_MBURST_SINGLE;
dma2_stream0.Init.PeriphBurst = DMA_PBURST_SINGLE;
if (HAL_DMA_Start(&dma2_stream0, (uint32_t)&GPIOC->IDR, (uint32_t)dma_buf0, BUF_LEN) != HAL_OK)
Checking in the DMA docs, DMA2, ch6, stream 0 maps to TIM1_TRIG. Is it correct that if TRGO from TIM1 is configured correctly it will time the transfer from the GPIO register correctly?
And the next question how do I setup correctly?
Is it only to enable TRG0 output from the timer, and set TIM->DIER = TIM_DIER_UDE? And then use the correct DMA channel, in this case for TIM1_CH1_TRIG = DMA2:ch6:stream0.
And is there a simple way to get the TRG0 from the rising flank of each output from the timer TIM1_CH1 or do I need to chain another timer to generate the correct timing for the sync to DMA.
BR,
/Johannes