cancel
Showing results for 
Search instead for 
Did you mean: 

Toggle mode confusion

durgesh777
Associate II
Posted on November 06, 2011 at 13:25

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-mode
5 REPLIES 5
Posted on November 06, 2011 at 16:03

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.

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 November 06, 2011 at 18:53

yes but the last paragraph with div2 is still mystery.

Posted on November 06, 2011 at 21:14

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

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 November 07, 2011 at 00:27

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.

Posted on November 07, 2011 at 04:27

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.

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