2011-11-06 04:25 AM
my IDE software shows following clock summary for my code:
HSECLK :8 Mhz SYSCLK :72 Mhz HCLK :72 Mhz PCLK1 :18 Mhz PCLK2 :72 Mhz I have following codes (only necessary lines are mentioned): __IO uint16_t CCR1_Val = 1; uint32_t PrescalerValue = 0; under main after setting clock, gpio and nvic: TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable); TIM_Cmd(TIM3, ENABLE); TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //CCR1 for output compare while (1) {} //end main and under the ISR: void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); capture=TIM_GetCapture1(TIM3); TIM_SetCompare1(TIM3, capture + CCR1_Val); } } So i get a pulse of width 625 us (micro second) and the period is around 1300 us. I had understood the resolution of the timer is 90000/72Mhz=1.25ms So when CCR1_val = 1, the timer interrupt should be accessed every 1.25ms. So the pulse width should be 1.25ms but it is half. Also if i increase the value of CCR1_val=2 the whole period is doubled and the pulse width becomes doubled and if CCR1_val=3 the pulse period is 4 ms and widht as 2 ms. Can anyone explains me why is it so. Specially the toggling mode is not understandeable for me. I had believed CCR1 value multiplied by the resoulution would be the time between which the interrupt service routine is served. Accordingly the pulse widht had to be the duration specified by CCR1 but here it seems that the whole period is the duration indicated by CCR1 and the pulse width is always with 50% duty cycle. Further if i make the following changes: RCC_PCLK1Config(RCC_HCLK_Div2); //which was Div4 previously CCR1_val=3; then the pulse width is 1ms and pulse period is 2 ms. I would be glad if someone could explain me. #stm-timer-3-toggle-mode2011-11-06 07:03 AM
I would be glad if someone could explain me.
Look more carefully at the clock tree diagram. The TIMCLK feed are *2 if you divide down the APB clock. Which means a 36 MHz APB, results in a 72 MHz TIMCLK, if your system runs at 72 MHz.2011-11-06 09:53 AM
yes but the last paragraph with div2 is still mystery.
2011-11-06 12:14 PM
__IO uint16_t CCR1_Val = 1;
uint32_t PrescalerValue = 0;
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
Your clock and prescaler value make no sense, there is no way the processor is going to be able to interrupt in the MHz range to advance the compare point in a meaningful way. It's simply going to saturate. If you clock the timer at 36 MHz, you probably want to program the prescaler with something like 36-1 or 36000-1 to get the timebase ticking along at 1 us or 1 ms increments. With a prescaler of zero (ie divide by 1), you'd need to have a CCR_Val of a few hundred or thousand. If you want to generate MHz frequencies you'd do much better using PWM, and program the width to get a 50/50 duty. One potential consequence of setting the CCR to a few hundred nano-seconds into the future, is that it might take more time to do the addition and write back the value, while the counter is still advancing. Figure the write to a peripheral is going to take at least 4 cycles. The result will be that the compare interrupt will occur the next time the counter gets around to the compare point, ie ~65536 cycles later at 36 MHz, or ~1.8 ms later than desired.
2011-11-06 03:27 PM
Sorry i apologize for missing a line,
Prescaler = (uint32_t) (SystemCoreClock / 800) - 1; That is why i have mentioned 90000 and i guess the timer would not saturate. Thank you very much.2011-11-06 07:27 PM
Sorry i apologize for missing a line,
Prescaler = (uint32_t) (SystemCoreClock / 800) - 1;
That is why i have mentioned 90000 and i guess the timer would not saturate.
The key problem here would be that the STM32F1xx parts only have 16-bit values for the Prescaler and Period, so 90000 isn't going to fit. You typically have to distribute large numbers between both of them to get the size/granularity you desire. Something like 36, 36000, or 7200 will give more standard units of time.