cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F205, SPL, TIM one-shot mode does trigger ADC

Raymond van Beek
Associate II
Posted on January 02, 2017 at 19:23

Hi there,

I am trying to get TIM4-CC4 in one-shot mode to trigger ADC1. It seems that TIM4 and CC4 is configured well: if enabled it generates interrupts on TIM_IT_CC4. So I am pretty sure CC4 fires.

I configured ADC1 for external triggering through the Timer 4 CC4 event. I checked various example codes, but still ADC does not seem to start a conversion: I don't get an interrupt at the end of conversion. I am pretty sure the ADC1 interrupt handler is Ok: when starting a converion from software, the interrupt handler is called allright.

I am using the Standard Peripheral Library for the STM32F2xx.

After days of trial and error, checking example software and reading the reference manual, I am out of inspiration 🙂 

There is no way of checking internal signals like CC, TRGI, TRGO, right?

Any way, I absolutely appreciate comments or suggestions!

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;

    TIM_OCInitTypeDef TIM_OCInitStruct;

    NVIC_InitTypeDef NVIC_InitStruct;

    ADC_CommonInitTypeDef ADC_CommonInitStruct;

    ADC_InitTypeDef ADC_InitStruct;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    // ======================================================================

    // == Configuration of Timer 4                                         ==

    // ======================================================================

    // - to be triggered by an rising edge on TIM3 TRGO output

    // - after 6.25 us, TIM4 OC4Ref must be set

    // - 1us later, the OC4Ref output can drop

    // - input capture on Zero Cross Detector input TIM_Ch1, pin D3

    // - max counter resolution, clock = 30 Mhz

    // - 30000000UL = 30 MHz Timer Clock = HCLK / 4

    // - counting up, measure time from zero count

    // - Pulse length: CCR register (TIM_OCInitStructure.TIM_Pulse): 6.25E-6 * 30000000 = 187

    // - Pulse+Delay length: The ARR register (TIM_TimeBaseStructure.TIM_Period): 7.25E-6 * 30000000 = 217

    TIM_TimeBaseStruct.TIM_Period = ((ZCD2PEAKDELAY + ADCSTARTPULSEWIDTH) * TIMCLK);

    TIM_TimeBaseStruct.TIM_Prescaler = 1;

    TIM_TimeBaseStruct.TIM_ClockDivision = 0;

    TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStruct);

    

    // - One Pulse is a special case of output compare mode

    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_Timing;

    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStruct.TIM_Pulse = (ZCD2PEAKDELAY * TIMCLK);

    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OC1Init(TIM4, &TIM_OCInitStruct);

    // - One single pulse when triggered

    TIM_SelectOnePulseMode(TIM4, TIM_OPMode_Single);

    // - counter starts when triggered from TIM3 TRGO

    TIM_SelectInputTrigger(TIM4, TIM_TS_ITR2);

    TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Trigger);

    // TIM enable counter

    TIM_Cmd(TIM4, ENABLE);

// OC4 can generate interrupt (code removed for clarity and TIM4 timing changes are seen, so probably ok....

    // ======================================================================

    // == Configuration of ADC                                             ==

    // ======================================================================

    // - to be triggered by a rising edge of TIM4_Ch4 output

    // - sample A0 analog input

    // - at EOC, DMA stores the result in memory

    // - Single ADC mode

    // - Sample at 30MHz clock (prescaler = 2)

    // - For now, no DMA

    // - No delay between ADC1 and ADC2 required

    ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;

    ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div2;

    ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

    ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

    ADC_CommonInit(&ADC_CommonInitStruct);

    // - 12 bits resolution (=> 15 clock cycles = 0.5 us)

    // - Single (one channel) scan mode

    // - Single scan, not continuous

    // - Trigger converion on a rising edge

    // - Trigger from TIM4_CC4

    // - Right aligned data, no scaling

    // - 1 conversion

    ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;

    ADC_InitStruct.ADC_ScanConvMode = ENABLE;

    ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;

    ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

    ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;

    ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;

    ADC_InitStruct.ADC_NbrOfConversion = 1;

    ADC_Init(ADC1, &ADC_InitStruct);

    // - Setup A0 input channel as single channel, with highest speed sampling

    ADC_RegularChannelConfig(ADC1, PIN_MAP[A0].adc_channel, 1, ADC_SampleTime_15Cycles);

    

    // - For now, disable DMA

    ADC_DMARequestAfterLastTransferCmd(ADC1, DISABLE);

    ADC_DMACmd(ADC1, DISABLE);

    

    // Temporary: for testing only

    NVIC_InitStruct.NVIC_IRQChannel = ADC_IRQn;

    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;

    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStruct);

    ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);

    ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);

    

    // Enable ADC

    ADC_Cmd(ADC1, ENABLE);

#output-compare #adc #tim #spl #stm32f205 #external-trigger #ons-shot
6 REPLIES 6
Posted on January 02, 2017 at 23:47

TIM_OC1Init(TIM4, &TIM_OCInitStruct);

// HOW DOES THIS USE TIM4_CC4 ??
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Raymond van Beek
Associate II
Posted on January 03, 2017 at 05:22

OMG, that was stupid... it was the remainder of one of my experiments

Changed that to:

TIM_OC4Init(TIM4, &TIM_OCInitStruct);

But still no luck, the ADC is still not triggered...

Posted on January 03, 2017 at 06:35

There's a lot missing...

I'll note the Period and Prescaler are N-1, so a prescaler of 1 is DIV2, the TIMCLK is twice the APB clock in this instance.

>>There is no way of checking internal signals like CC, TRGI, TRGO, right?

You can get TIM4_CC4 to a pin, if you don't see a waveform there the ADC isn't going to trigger, work back from there.

You could get the trigger input to reset the counter, with a maximal period you should be able to see by observation that the count doesn't go full cycle.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on January 12, 2017 at 21:27

Thanks for your suggestions, Clive!

The TIMCLK being twice the APB clock: This means that the counters are counting at the double speed as the registers are clocked, right? Could that lead to problems?

I have tried to connect the EXTI line 11 to an input pin. Unfortunately I have a WM-N-BM-09 WICED module, where the STM32F205 is mounted below a wifi chip. The GPIO pin connected to the EXI Line 11 is not available for connection.

So I concentrated on trying different external trigger sources: I tried not only TIM5 but also TIM8 which can also be selected as external ADC trigger, both TRGO and CC1, both unsuccessfull. These timers do run properly (I checked by means of an timer interrupt handler, which triggers with the right period).

Since I also am able to start ADC conversions through software (ADC_SoftwareStartConv(ADC1)), including an interrupt handling the EOC, I suspect a missing configuration of the link between a timer and the ADC external trigger circuit.

I have some questions on triggering the ADC from an external source:

  • When setup for external triggering CR2.EXTEN=0x01, must conversions still be enabled through CR2.SWSTART or an other register?
  • When setup for external triggering on a CC event (e.g. CR2.EXTSEL = 1101 - Timer 8 CC1 event), must this CC event be released by some register?
  • When setup for external triggering on a TRGO event (e.g. CR2.EXTSEL = 1110 - Timer 8 TRGO event), must this TRGO event be released other than by TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_OC1Ref) and TIM_SelectMasterSlaveMode(TIM8, TIM_MasterSlaveMode_Enable)
  • Is the CC event only available when the associated GPIO pin is configured as AF Alternative Function?
  • Does the trigger link between timers and ADC require some special clock configuration RSS?

I also noticed that the start/trigger registers for the ADC in STM32F2xx differ somewhat from the STM32F1xx.

Ben Voigt
Associate II
Posted on January 16, 2017 at 21:15

I'm answering based on the STM32L471 chip I'm using since I just spent over a day stumbling through the undocumented bits of hardware trigger setup; it seems to have the same ADC and timer peripherals.

  • When setup for external triggering CR2.EXTEN=0x01, must conversions still be enabled through CR2.SWSTART or an other register?Yes.  When EXTEN=00, ADSTART is a trigger signal (resets after the conversion completes).  When EXTEN has any other value, ADSTART becomes an enable latch.  Hardware trigger signals are ignored when ADSTART=0.  This is described in the reference manual section 'Starting Conversions (ADSTART, JADSTART)'.
  • When setup for external triggering on a CC event (e.g. CR2.EXTSEL = 1101 - Timer 8 CC1 event), must this CC event be released by some register?Yes.  The ADC trigger is edge-sensitive (see description of EXTEN) so the output compare mode set in CCMRj in the timer must be a PWM mode, since those produce regular edges.  Also, the output enable for that channel must be enabled in CCER.
  • When setup for external triggering on a TRGO event (e.g. CR2.EXTSEL = 1110 - Timer 8 TRGO event), must this TRGO event be released other than by TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_OC1Ref) and TIM_SelectMasterSlaveMode(TIM8, TIM_MasterSlaveMode_Enable)I didn't use the TRGO signal for ADC triggering, since I need it for another purpose.
  • Is the CC event only available when the associated GPIO pin is configured as AF Alternative Function?No, it's enough to enable the output from the timer peripheral, you do not need to have any pin connected.
  • Does the trigger link between timers and ADC require some special clock configuration RSS?The reset/clock control needs to be configured properly for the timer and the ADC (remember to both enable clock for the register bus interface and also the timebase / sampleclock which these peripherals use internally).  There wasn't any additional RCC settings needed to make the hardware trigger work.
Posted on January 16, 2017 at 21:50

The F2/F4 are very similar, they differ from the F1 in numerous ways as ST learned a lot of things, and improved/fixed them in subsequent designs.

You don't have to get triggers to pins, but it helps to see them if you think things are broken.

The TIM, ADC and DMA clocks need to be enabled, I'd generally enable ALL the clocks I need in one subroutine rather than pick my way through them as I initialize specific peripherals. Also usually put all the GPIO stuff in one place.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..