cancel
Showing results for 
Search instead for 
Did you mean: 

How to Trigger ADC1 with TIM1_CH4?

jerry2
Senior

On the STM32F401RE, I'm trying to get a compare match on CC4 on TIM1 to trigger an ADC conversion in injected mode, but the ADC is never seeing the trigger.

How do I set TIM1 to generate the TIM1_CH4 trigger on a compare match on CC4?

TIM1->CR2 has an MMS field, which can be set to 0b111 to generate TRGO from CC4REF, but there's nothing here to indicate how to set TIM1 to generate TIM1_CH4 from CC4REF.

As described in the reference manual, the ADC has many injected group trigger options, including TIM1_TRGO and TIM1_CH4, but nothing in the TIM1/TIM8 section of the manual says anything about how to enable TIM1_CH4. Is it always enabled?

I'm using TIM1 to generate three PWM outputs, on channels 0-3, for motor control, and I'm using channel 4 to generate a ADC trigger to read motor phase currents with the right timing. When I set channel 4 to interrupt on a compare match, I do get those interrupts, indicating a compare match has occurred, but it either doesn't generate a TIM1_TRGO or a TIM1_CH4 trigger or the ADC never sees it, because the ADC never starts an injected group conversion.

I've tried changing the settings to use TIM1_TRGO to trigger the ADC, but that didn't work either.

I have the following settings for:

TIM1->CR1 = TIM_CR1_ARPE | (0b10 << TIM_CR1_CMS_Pos); 
    TIM1->CR2 =  0b111 << TIM_CR2_MMS_Pos; 
    TIM1->SMCR = 0;                              
    TIM1->DIER = TIM_DIER_CC4IE;   
    TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1PE |
                        TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2PE; 
    TIM1->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0 | TIM_CCMR2_OC3PE | 
                        TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_0 | TIM_CCMR2_OC4PE;
    TIM1->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E;  
    TIM1->BDTR = TIM_BDTR_MOE;                    

And for the ADC:

    ADC1[0]->CR1 = 0;  
    ADC1[0]->CR1 = ADC_CR1_JEOCIE; 
    ADC1[0]->CR2 = (0b01 << ADC_CR2_JEXTEN_Pos) | (0b0001 << ADC_CR2_JEXTSEL_Pos) | ADC_CR2_ADON; 
 
    ADC1[0]->SMPR1 = (0b001 << ADC_SMPR1_SMP10_Pos) |  (0b001 << ADC_SMPR1_SMP11_Pos); 
    ADC1[0]->SMPR2 = (0b01 << ADC_SMPR2_SMP0_Pos);  
 
    ADC1[0]->JSQR = (0 << ADC_JSQR_JL_Pos) | (0 << ADC_JSQR_JSQ1_Pos);      
    ADC->CCR |=  (0b11 << ADC_CCR_ADCPRE_Pos); 

9 REPLIES 9
Piranha
Chief II

ADC has a power-up delay of maximum 3 us after setting ADON. Check if CR1 and the rest of the CR2 bits are configured at all.

A note at ADC_JSQR register in reference manual:

When JL=0 (1 injected conversion in the sequencer), the ADC converts only JSQ4[4:0] channel.

For code I would suggest this style:

TIM1->CR2 = _VAL2FLD(TIM_CR2_MMS, 0b111);
TIM1->CCMR1 = _VAL2FLD(TIM_CCMR1_OC2M, 0b111) | TIM_CCMR1_OC2PE | _VAL2FLD(TIM_CCMR1_OC1M, 0b111) | TIM_CCMR1_OC1PE;

Also ADC1[0] looks confusing and has a potential for a (future) conflict. If it's an array, then a number 1 seems confusing. And, as all uppercase names are typically used for macros and constants, variables should be either CamelCase or lowercase.

Thanks for the reply. I initialize the ADC very early on and start the timer that triggers the ADC several hundred milliseconds after initializing it. CR1 and CR2 are both configured as I expect right before the first timer trigger is supposed to take place.

I discovered the oddness regarding JSQR register and the order it converts the injected channels. It's strange they implemented it this way because if you want to convert two channels, you put the two channel numbers in JSQ3 and JSQ4 (in that order), but if you later want to convert four channels, including the two original channels preserving the order of those two channels, you have to copy the two original channel numbers from JSQ3 and JSQ4 to JSQ1 and JSQ2. Odd, also, that they didn't do it this way with regular sequences.

I'll take your style suggestions under advisement. ;)

Now back to the real question at hand: what's preventing the timer from triggering the ADC injected sequence and do I need to use TIM1_TRGO or TIM1_CH4 (and, if so, how do I configure the timer registers to do that, because TIM1_CH4 is mentioned in the ADC section of the reference manual, but not in the TIM1/TIM8 section)?

This is something which is (probably - didn't check for quite some time) not described clearly enough in the RM (not in ADC nor in the Interconnections chapter, latter of which in case of 'F4 is for historical reasons a separate AN) - the TIMx_CHy options for ADC triggering work directly from the TIMx_CHy output signal of the TIM module. This signal is normally used as input to the GPIO module to drive a pin according to the GPIO AF matrix setting, but it is also connected directly to the ADC trigger demultiplexer.

In other words, do everything you would do to get a pulse train going on a TIMx_CHy pin, except you don't need to set anything in GPIO (i.e. you don't really have a pin assigned to TIMx_CHy). In TIM1 that involves not only TIMx_CCER.CCxE, but also TIMx_BDTR.MOE to be set.

JW

(mentioned with link to relevant discussion in this gotcha :) )

Hi JW. Thanks for the reply.

Your suggestion to enable TIM1_CCER.CC4E was a good one that I hadn't thought of. I tried setting it, but, unfortunately, I'm still not getting injected sequence triggers from TIM1 in the ADC.

I do have the pulse train going on TIM1_CH4 as I've enabled its interrupt and I am getting the interrupt at the appropriate time (and verified by toggling a GPIO output in the ISR and seeing it on an oscilloscope).

Here's the current setting of the relevant registers on TIM1 and ADC1:

TIM1->CR1 = TIM_CR1_ARPE | (0b10 << TIM_CR1_CMS_Pos);
TIM1->CR2 =  0b111 << TIM_CR2_MMS_Pos;
TIM1->SMCR = 0; 
TIM1->DIER = TIM_DIER_CC4IE;
TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 | TIM_CCMR1_OC1PE | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2PE; 
TIM1->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0 | TIM_CCMR2_OC3PE | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_0 | TIM_CCMR2_OC4PE;
TIM1->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E;
TIM1->BDTR = TIM_BDTR_MOE;       
 
ADC1->CR1 = 0;
ADC1->CR1 = ADC_CR1_JEOCIE;
ADC1->CR2 = (0b01 << ADC_CR2_JEXTEN_Pos) | (0b0001 << ADC_CR2_JEXTSEL_Pos) | ADC_CR2_ADON; 
ADC1->SMPR1 = (0b001 << ADC_SMPR1_SMP10_Pos) | (0b001 << ADC_SMPR1_SMP11_Pos); 
ADC1->SMPR2 = (0b01 << ADC_SMPR2_SMP0_Pos); 
ADC1->JSQR = (0 << ADC_JSQR_JL_Pos) | (0 << ADC_JSQR_JSQ4_Pos); 
ADC->CCR |=  (0b11 << ADC_CCR_ADCPRE_Pos);

I've tried setting ADC_CR2_JEXTSEL to both 0b0000 and 0b0001 and neither work. At this point I'm still not clear on whether the problem is on the TIM1 side (it not generating an event when a CC4 compare occurs) or the ADC1 (it not starting an injected sequence conversion when it gets an event from TIM1).

jerry2
Senior

Okay, I found the problem...

I'm using TIM1 to generate center-aligned PWM on channels 1-3 for motor control and wanted to trigger the ADC to read motor current right in the middle of the PWM cycle. To do this, I was programming TIM1->CCR4 to the same value as TIM1->ARR. I was getting CC4 interrupts (TIM1->DIER.CC4IE), so I thought everything was working as expected and TIM1 would generate the event that triggered ADC1.

When I changed TIM1->CCR4 to TIM1->ARR - 1 everything started working. So apparently if CCR4 is set to the same value as ARR, compare interrupts will happen, but not trigger events. Hmmm...

Thanks for the link to the STM32 Gotchas site. This issue seems to be covered by gotcha #31, but not exactly, because that gotcha implies that both interrupts and triggers will be generated. I'm seeing interrupts, but not triggers.

I'll definitely read that list of gotchas and perhaps I'll find solutions to other weird STM32 issues I've been puzzling over.

As I've said, the ADC is triggered by exactly the same signal which goes to the TIM_CHx pin. If you enable such pin and you don't see any edge - which you won't if you set TIM1_CCR4 to TIM1_ARR - the ADC won't get triggered.

JW

Piranha
Chief II

111: PWM mode 2 - In upcounting, channel 1 is inactive as long as TIMx_CNT<TIMx_CCR1

else active.

The CNT register reaches the ARR value and stays at it for a period of one CNT clock cycle. Shouldn't the channel be active for that one cycle?

I agree, and that's what I would expect it to do. What was fooling me was the fact that it was generating the CC4 interrupt even though it wasn't generating the ADC trigger.

0693W00000NpGDnQAN.png 

PWM2 is just inversion of PWM1.

IMHO it boils down to the exact moment when DIR changes, which is not drawn on these diagrams, unfortunately. But, honestly, I try to stay away from the up-down counting modes as far as it's possible.

JW