cancel
Showing results for 
Search instead for 
Did you mean: 

External (Timer) trigger for regular ADC channel

SzIsti
Associate II

Hi everyone!

So as the title suggest I would like to get some help for my STM32F303 Microcontroller.

In the application Timer1 is used to turn an external pin ON and OFF at a constant frequency, while ADC4 is used to read some feedback with the same frequency, preferably with an exact and very short delay each time.

Currently the Timer1 interrupt both toggles the GPIO state AND triggers the ADC4 conversion through software trigger. I have been told that a more efficient result can be achieved by linking the ADC4 to Timer1, so the trigger is faster and more reliable.

Going through the Reference manual I have found the way to do it, however Timer1 Channel3 just doesnt want to trigger. It triggers only once, if the detection is at Falling edge. It also messes up the NVIC, and the other channels of Timer1 are not working properly as well.

I have found out however, that if I link it to Timer2 Channel 3 it works correctly. That timer is used for a separate PWM signal generation at a complete different frequency.

I am puzzled why it is working for TImer2 but not for Timer1. I read it somewhere, that the OCMode should be set to PWM1, but for Timer1 it doesn't help.

See below attached code sections

Timer1 initialization:

	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	//TIM_TimeBaseStructure.TIM_Period = 11076/4;       // original line of below
	timPeriod = 72000000/(g_laserPeriod*PWM_RES);		// 130000Hz / 72000000Hz = 553,8 counts - 1; 7,69uS period
	TIM_TimeBaseStructure.TIM_Period = timPeriod;
	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
 
	/* Output Compare Toggle Mode configuration: Channel3 */
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;//TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
	TIM_OCInitStructure.TIM_Pulse = 0x00;
	TIM_OC3Init(TIM1, &TIM_OCInitStructure);
	TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

Timer2 initialization:

    tim_time_base_structure.TIM_ClockDivision = TIM_CKD_DIV1;
    tim_time_base_structure.TIM_CounterMode = TIM_CounterMode_Up;
    tim_time_base_structure.TIM_Period = 4096;			//72MHz / 4096 = 17574 Hz
    tim_time_base_structure.TIM_Prescaler = 0;
    tim_time_base_structure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &tim_time_base_structure);
 
    tim_oc_init_structure.TIM_OCMode = TIM_OCMode_PWM1;
    tim_oc_init_structure.TIM_OCIdleState = TIM_OCIdleState_Reset;
    tim_oc_init_structure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
    tim_oc_init_structure.TIM_OutputState = TIM_OutputState_Enable;//ENABLE;
    tim_oc_init_structure.TIM_OutputNState = TIM_OutputNState_Disable;
    tim_oc_init_structure.TIM_OCPolarity = TIM_OCPolarity_High;
    tim_oc_init_structure.TIM_OCNPolarity = TIM_OCNPolarity_High;
    tim_oc_init_structure.TIM_Pulse = 50;  /* CC3 */
    TIM_OC3Init(TIM2, &tim_oc_init_structure);
    tim_oc_init_structure.TIM_Pulse = 50;  /* CC4 */
    TIM_OC4Init(TIM2, &tim_oc_init_structure);
    TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);

 ADC4 initalization:

	/* ADC4 configuration ------------------------------------------------------*/
	adc_init_structure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Disable;		//continuous conversion  (TEMPOR_ISS to Disable)
	adc_init_structure.ADC_Resolution = ADC_Resolution_12b;							//12bit resolution
	adc_init_structure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_2; 	//External trigger on TIM1_CC3
	adc_init_structure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_RisingEdge;	// Rising edge trigger
	adc_init_structure.ADC_DataAlign = ADC_DataAlign_Right;							//Right alignment
	adc_init_structure.ADC_OverrunMode = ADC_OverrunMode_Disable;					//
	adc_init_structure.ADC_AutoInjMode = ADC_AutoInjec_Disable;
	adc_init_structure.ADC_NbrOfRegChannel = 1;
	ADC_Init(ADC4, &adc_init_structure);
	ADC_AutoDelayCmd(ADC4, ENABLE);
 
	/* ADC4 regular channels configuration */
	ADC_RegularChannelConfig(ADC4, ADC_PD_TEST_AC_CHANNEL, 1, ADC_SampleTime_19Cycles5); // approx. 271ns sample time

5 REPLIES 5

Perhaps you can try a little harder to formulate a question with some specific context about the part, and behaviour.

The Reference Manuals and Data Sheets typically provide details of functional connections, and external pinage.

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

I was just editing the details, you can see it now

Ok, so edited, still not seeing code.

The behaviour between triggers tends to be pretty consistent, but you have to get a number of TIM setting and libraries calls using coherent settings. Selecting the right trigger outputs, etc. Some TIM only available on certain APB

Attach files via paper clip icon, might not be available in all views, edit messages seem to lack options. If multiple files involved ZIP them up and attach ONE

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

For TIM1 you need to clear and fill out a much larger tim_oc_init_structure as TIM1 and TIM8 are special/advanced timers.

And also explicitly enable PWM output

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

Thank you, I will check it out tomorrow. I didn't expect a response this fast =)

The thing is that I dont want to have real PWM output for Timer1. But I will see what can i do about it.

EDIT: So I was looking into it today, defining all value in the init_structure and setting the OCMode to PWM1, but it still didn't work out. However some changes in the interrupt handler made the timing more accurate, so maybe I don't have to link them together, at least for now.