2012-01-04 05:56 AM
PROBLEM: Timer interrupt is entered immediately in the beginning and not in the desired timing period.
The objective is to enter a service routing of TIM4 with a timing of every 10 sec, clock is 72Mhz: TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler = 39999; TIM_TimeBaseStructure.TIM_ClockDivision = 1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); // OCMode Active configuration: Channel1 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 18000; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC1Init(TIM4, &TIM_OCInitStructure); // interrupt on update TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM4, ENABLE); // TIM4 enable counter TIM_Cmd(TIM4, ENABLE); The interrupt service routine is entered immediately after the beginning and not after 5 seconds. I would be happy if someone could help me on this. #dividers-and-prescaler-division #tim-problem #know-thy-tools2012-01-04 04:09 PM
So 5 seconds, or 10 seconds? Because at the moment the math has you at 41 seconds for a 72 MHz clock.
72,000,000 / (40000 * 65536) = 0.0274658 Hz 10 Seconds is 0.1 Hz 72,000,000 * 10 = 720,000,000 (Cycles in 10 Seconds @ 72 MHz) Lets factor that for some 16-bit values 720,000,000 / 50,000 = 14,400, or 7,200 * 2 720,000,000 / 60,000 = 12,000 Finally, you need to make sure the pending update flag is cleared BEFORE enabling the interrupt.void TIM4_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// TIM_TimeBaseStructure.TIM_Prescaler = (800 * 2) - 1; // 8 MHz clock source, 8000 for 2 ms, 800 for 0.2 ms ticks
TIM_TimeBaseStructure.TIM_Prescaler = (7200 * 2) - 1; // 72 MHz clock source, 0.2 ms ticks
TIM_TimeBaseStructure.TIM_Period = 50000 - 1; // 0.2 ms units, 10 second update
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
// TIM4 enable counter
TIM_Cmd(TIM4, ENABLE);
// Clear pending update interrupt
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
// Enable interrupt on update
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
}
2012-01-05 11:07 AM
The math is:
72Mhz/40k = 1800 Hz (and 40k is valid for 16 bit, as limit is 65535) so the calculated time is 18000/1800 = 10 s. The value 18000 is allocated for the Capture Compare Register. May be the clock division should be 0 (i.e. 1 in actual division) instead of 1(i.e. 2 in actual division and so. that makes timer frequency 900 Hz in such case). So the question would be what would be the function of Capture Compare (CC) Register? Here ARR is set to 65535. The objective was to generate an interrupt at every overflow of CC register and immediately sett the counter to zero so that the timer cannot go beyond CC value. In such case i can write immediately under TIM4 service routine as, if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM4, TIM_IT_Update); TIM4->CNT=0; ------ISR------ } Now what should be the function to be written under ISR, instead of the following: if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)2012-01-05 12:48 PM
Using the CCR seems to require a lot of unnecessary work, and causes the clock to drift/slew. The code I presented generates an update interrupt every 10 seconds, and you just check/clear the Update interrupt flags.
If you want to play the chase the CCR game, you should in fact just advance a variable for the CCR % 65536 (16-bit), rather than try to reset the primary counter. Or modulo whatever the ARR is, but using 65536 saves an expensive divide. The main reason to use CCRx implementations would be if you wanted to use all 4-channels, and have different interrupt beat frequencies. Further, you'd need to be using the CC1 interrupt, not the Update interrupt. You can't check for one interrupt source, and clear another, it doesn't work like that. My interrupt code looked like thisvoid TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
/*------ISR------*/
}
}
2013-01-09 06:32 AM
hi,
What is the clock divisionvariation interval
Please 0, 1 .. What else ? can it be 0.5 ? 10 ? Thanks2013-01-09 06:42 AM
What is the clock division
variation interval
Please 0, 1 .. What else ? can it be 0.5 ? 10 ? /** @defgroup TIM_Clock_Division_CKD * @{ */ #define TIM_CKD_DIV1 ((uint16_t)0x0000) #define TIM_CKD_DIV2 ((uint16_t)0x0100) #define TIM_CKD_DIV4 ((uint16_t)0x0200) The clock period and prescaler are generally 16-bit integers, and you have to factor the values accordingly.2013-01-09 07:55 AM
exuse me but i don't see any difference betwen signal using
TIM_TimeBaseStructure.TIM_ClockDivision
= TIM_CKD_DIV1
TIM_TimeBaseStructure.TIM_ClockDivision
= TIM_CKD_DIV2
TIM_TimeBaseStructure.TIM_ClockDivision
= TIM_CKD_DIV4
It gives the same signal in my oscilloscope
How can I change
TIM_ClockDivision
to shift time signal please
2013-12-27 02:33 AM
Hi clive,
I am having nearly the same problem. Developing code for SMT32F205RG using KEIL. I copied the code that you shared in this thread and execute it in step by step in KEIL debug. I realized that the following command that is expected to clear update flag does not work if TIM4 is enabled.TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
the code hits to this line but after execution of that line TIM4->SR remains unchanged (0x001F).
Then I changed the sequence of timer enable and clear flag function calls as follows: First cleared all the the flag and verified that it is cleared (while TIM4 is not enabled):// Clear pending update interrupt
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
// TIM4 enable counter
TIM_Cmd(TIM4, ENABLE);
As soon as enabling the TIM4, all interrupts are set. (TIM4->SR:0x001F) isn't it weird? Do you have any suggestion for that problem? What would be the root cause?
2013-12-27 04:14 AM
I think I've just found the root cause :)
In RM0033 referenece manual this case was mentined as follows:14.3.16 Debug modeWhen the microcontroller enters debug mode (Cortex™-M3 core - halted), the TIMx countereither continues to work normally or stops, depending on DBG_TIMx_STOP configurationbit in DBGMCU module. For more details, refer to Section 32.16.2: Debug support fortimers, watchdog, bxCAN and I2C.So, I have finalized my 7-8 hours of digging code with the following summary:''do not trust the results in DEBUG mode if you are working with timers :) ''2013-12-27 05:43 AM
''do not trust the results in DEBUG mode if you are working with timers''
I think that would be better stated as, ''be sure to understand the effects of the debugger on the system under test''.In particular, breakpoints, halting, and single-stepping are bound to disrupt timing & interrupt responses to some degree...Another point that clive1 often makes is that observing a peripheral via a debugger's peripheral viewer is likely to affect the state of that peripheral...It's just like taking measurements in hardware circuits affects the state of the circuit...