cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with Timing

durgesh777
Associate II
Posted on January 04, 2012 at 14:56

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-tools
10 REPLIES 10
Posted on January 05, 2012 at 01:09

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);
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
durgesh777
Associate II
Posted on January 05, 2012 at 20:07

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)

Posted on January 05, 2012 at 21:48

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 this

void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
/*------ISR------*/
}
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
bmwael1
Associate II
Posted on January 09, 2013 at 15:32

hi,

What is the clock division

variation interval

Please

0, 1 .. What else ? can it be 0.5 ? 10 ?

Thanks

Posted on January 09, 2013 at 15:42

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.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
bmwael1
Associate II
Posted on January 09, 2013 at 16:55

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 0690X00000602nEQAQ.jpg
bugra
Associate II
Posted on December 27, 2013 at 11:33

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?

bugra
Associate II
Posted on December 27, 2013 at 13:14

I think I've just found the root cause 🙂

In RM0033 referenece manual this case was mentined as follows:

14.3.16 Debug mode

When the microcontroller enters debug mode (Cortex™-M3 core - halted), the TIMx counter

either continues to work normally or stops, depending on DBG_TIMx_STOP configuration

bit in DBGMCU module. For more details, refer to Section 32.16.2: Debug support for

timers, 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 🙂 ''

Andrew Neil
Chief II
Posted on December 27, 2013 at 14:43

''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...