cancel
Showing results for 
Search instead for 
Did you mean: 

TIM-triggered periodic ADC capture w/ DMA

BMcDo.3
Associate III

I'm trying to do a periodic ADC capture on 2 channels, triggered by TIM5. ADC should output to memory via DMA, with a DMA interrupt upon each completion to read the data from each scan.

So far, the DMA interrupts aren't hitting, and the ADC doesn't even appear to be reading anything. Any ideas what I'm missing?

TIM5_CC4 outputs on a GPIO. ADC captures should be synced with that, so I'm trying to use TIM5_CC3 to trigger the ADC.

Code was generated by STM32CubeMX 6.1.1, with STM32F4 package 1.25.2. (MX_DMA_Init() is called before MX_ADC1_Init().)

CubeMX Project Screenshots

0693W00000JNQtTQAX.png 

0693W00000JNQtiQAH.png 

0693W00000JNQtsQAH.png 

0693W00000JNQtxQAH.png 

0693W00000JNQu7QAH.png 

0693W00000JNQuCQAX.png 

0693W00000JNQuRQAX.png 

0693W00000JNQugQAH.png 

0693W00000JNQv0QAH.png 

0693W00000JNQtPQAX.png 

Code Excerpts

Order of some relevant function calls:

// in main():
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
 
  // elsewhere, after OS starts:
  MX_ADC1_Init();

 EDIT: Added relevant code excerpts as attachments.

1 ACCEPTED SOLUTION

Accepted Solutions

Thanks for your help.

On further investigation, I see no sanctioned way with the (non-LL) HAL to enable the channels before starting the PWM output.

I'm working around the issue by (ab)using the private function TIM_CCxChannelCmd(). I've replaced

  TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_4, TIM_CCx_ENABLE);

with

  TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_3, TIM_CCx_ENABLE);
  TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_4, TIM_CCx_ENABLE);
 
  HAL_TIM_Base_Start(&htim5);

EDIT: the DMA interrupts aren't correct yet. The interrupt gets hammered for a while, then isn't called anymore. I think the ADC config isn't correct. But I'm over the main roadblock now.

View solution in original post

9 REPLIES 9
KnarfB
Principal III

use the timer update event for TRGO, not the reset event.

Changed as specified. Problem persists, i.e. HAL_ADC_ConvCpltCallback() still isn't called.

0693W00000JNSDPQA5.png0693W00000JNSF1QAP.png 

Which STM32?

Read out and check/post TIM, ADC and DMA registers content.

JW

Here is a working project for an F0.

Did you start

  HAL_TIM_Base_Start(&htim1);
  HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buf, ADC_BUF_LEN);

hth

KnarfB

> Did you start...

1. No, actually - we call

HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_4);

Maybe this is the problem, as it doesn't start TIM_CHANNEL_3? How would I start them both at the same time, and produce the same output as this does on CHANNEL_4? (HAL_TIM_PWM_Start only takes single channel args.)

EDIT: Maybe HAL_TIM_PWM_ConfigChannel() before HAL_TIM_Base_Start()? I'm looking into it...

2. Yes, MX_ADC1_Init() --> HAL_ADC_Init() --> HAL_ADC_MspInit(), which includes

  /* USER CODE BEGIN ADC1_MspInit 1 */
 
    static uint32_t dummyData[2];
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)dummyData, 2);
 
  /* USER CODE END ADC1_MspInit 1 */

(Trying to get it going before I bother actually trying to capture the data...)

Start HAL_TIM_OC_Start (?) TIM_CHANNEL_3 next line. This should not affect sync. because all channels share the same time counter (CNT register).

> Start HAL_TIM_OC_Start (?) TIM_CHANNEL_3

Did you mean HAL_TIM_PWM_Start()?

EDIT: I see HAL_TIM_OC_Start() is identical to HAL_TIM_PWM_Start().

> next line. This should not affect sync.

What I mean is not only do I need them in sync for steady state operation. Also the first pulse output from both channels (3 & 4) must be simultaneous, i.e. never a pulse on just one of them.

I thought the Start functions actually start the timer, and so separate calls to HAL_TIM_PWM_Start() / HAL_TIM_OC_Start() would risk missing some initial pulses on one channel?

> Did you mean HAL_TIM_PWM_Start()?

correct, you are using PWM mode

Its correct the you might miss one or more PWM events if you start the 2nd channel too late. How realistic this threat is, depends on the ... timing. You might read back the counter (__HAL_TIM_GET_COUNTER) register and check how many ticks you have spent in the HAL code and if this comes close to the PWM edges. If this sounds risky, you might want to go register level or low level (LL_) programming.

Thanks for your help.

On further investigation, I see no sanctioned way with the (non-LL) HAL to enable the channels before starting the PWM output.

I'm working around the issue by (ab)using the private function TIM_CCxChannelCmd(). I've replaced

  TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_4, TIM_CCx_ENABLE);

with

  TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_3, TIM_CCx_ENABLE);
  TIM_CCxChannelCmd(htim5.Instance, TIM_CHANNEL_4, TIM_CCx_ENABLE);
 
  HAL_TIM_Base_Start(&htim5);

EDIT: the DMA interrupts aren't correct yet. The interrupt gets hammered for a while, then isn't called anymore. I think the ADC config isn't correct. But I'm over the main roadblock now.