2009-12-27 09:55 AM
Problem setting up Timer for output compare match
2011-05-17 04:35 AM
Hi,
I am new to the STM32 and slowly working my way through the different peripherals (even over Christmas ;-)). I am wanting to generate two timer output compare match events every 2.5ms and 2ms to trigger ADC conversions over a number of channels. Looking through the Standard Peripherals Firmware Library (3.1.2), I have come up with the timer configuration listed below. The ADC is configured to respond to the ADC_ExternalTrigConv_T1_CC1/2 event. What happens when I run the code is that the ADC gets triggered at the end of each timer period (82ms), and not by the expected output compare match CCR1/2 values. So obviously the setup for the timer is wrong, but after trawling through other code examples and the Reference Manual for 2 days, I still can't see the error. Any help would be greatly appreciated. Thanks PeterCode:
<BR><BR>void TIM1_Configuration(void) <BR><BR>{ <BR><BR> /* ------------ <BR><BR> TIM1 Configuration: generate 2 signals with 2 different delays: <BR><BR> TIM1CLK = 72 MHz, Prescaler = 720, TIM1 counter clock = 100 KHz <BR><BR> TIM1_CH1 delay = CCR1_Val/TIM1 counter clock = 2.5 ms <BR><BR> TIM1_CH2 delay = CCR2_Val/TIM1 counter clock = 2 ms <BR><BR> ------------ */ <BR><BR> uint16_t CCR1_Val = 250; <BR><BR> uint16_t CCR2_Val = 200; <BR><BR> <BR><BR> /* Time base configuration */ <BR><BR> TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); <BR><BR> TIM_TimeBaseStructure.TIM_Period = 4095; <BR><BR> TIM_TimeBaseStructure.TIM_Prescaler = 720; <BR><BR> TIM_TimeBaseStructure.TIM_ClockDivision = 0; <BR><BR> TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; <BR><BR> TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); <BR><BR> <BR><BR> /* Output Compare Active Mode configuration: Channel1 */ <BR><BR> TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; <BR><BR> TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; <BR><BR> TIM_OCInitStructure.TIM_Pulse = CCR1_Val; <BR><BR> TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; <BR><BR> TIM_OC1Init(TIM1, &TIM_OCInitStructure); <BR><BR> TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable); <BR><BR> <BR><BR> /* Output Compare Active Mode configuration: Channel2 */ <BR><BR> TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; <BR><BR> TIM_OCInitStructure.TIM_Pulse = CCR2_Val; <BR><BR> TIM_OC2Init(TIM1, &TIM_OCInitStructure); <BR><BR> TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Disable); <BR><BR> <BR><BR> /* Enable Auto Reload */ <BR><BR> TIM_ARRPreloadConfig(TIM1, ENABLE); <BR><BR>} <BR>
Code:
<BR>void ADC1_Configuration(void) <BR>{ <BR> /* ADC1 configuration ---*/ <BR> ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; <BR> ADC_InitStructure.ADC_ScanConvMode = ENABLE; <BR> ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; <BR> ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; <BR> ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; <BR> ADC_InitStructure.ADC_NbrOfChannel = 3; <BR> ADC_Init(ADC1, &ADC_InitStructure); <BR> <BR> /* ADC1 regular channels configuration */ <BR> ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_7Cycles5); <BR> ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_7Cycles5); <BR> ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_7Cycles5); <BR> <BR> /* Enable ADC1 DMA */ <BR> ADC_DMACmd(ADC1, ENABLE); <BR> <BR> /* Enable ADC1 external trigger */ <BR> ADC_ExternalTrigConvCmd(ADC1, ENABLE); <BR> <BR> /* Enable EOC interrupt */ <BR> // ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); <BR> <BR> /* Enable ADC1 */ <BR> ADC_Cmd(ADC1, ENABLE); <BR> <BR>
[ This message was edited by: peter_lanius on 25-12-2009 11:31 ]2011-05-17 04:35 AM
Hi,
if you don't update the CCx channel by interrupt or DMA, it will trigger ADC conversion only once per period (...) because in output mode the CCx is a static compare value and the match happens only once per period (in triangular mode twice). Next, ADC will be triggered only by one selected channel, not by combination CC1/CC2. Moreover, ADC EOC interrupt occurs after ALL channels are converted, thus you need DMA to transfer all conversion results to memory. If you need ADC triggered peridically with higher freq. than your timer intends to, use another timer for ADC and trigger their start synchronously using timer link system.2011-05-17 04:35 AM
Thanks edison. Makes sense now.