cancel
Showing results for 
Search instead for 
Did you mean: 

TIM3 wrong counting?

jheilig999
Associate II
Posted on September 04, 2012 at 17:14

I need to generate a 20 ms interrupt into my firmware. HSE is 16 Mhz with STM8S208.

I put this initialization code into my firmware to accomplish that through the use of TIM3:

#define PRESC TIM3_PRESCALER_32  

    uint16_t counter = 10000;

 

    //counter = counter / 4 * 3; //correction to run closer to a 20 ms period

 

    TIM3_UpdateRequestConfig(TIM3_UPDATESOURCE_GLOBAL);

 

    TIM3_TimeBaseInit(TIM3_PRESCALER_32, counter);

 

    TIM3_UpdateDisableConfig(DISABLE);

 

    TIM3_PrescalerConfig (PRESCALER_32, TIM3_PSCRELOADMODE_UPDATE);

 

    TIM3_ARRPreloadConfig(ENABLE);

 

    TIM3_ITConfig(TIM3_IT_UPDATE, ENABLE);

 

To achieve the desired 20 ms period I initialized the counter to 10000, so that (16 Mhz / 32 presc = 500 Khz) / 10000 = 50 Hz.

Unfortunately the actual frequency is 75% of the expected one, so I need to uncomment the counter correction statement.

Does someone why does this happen?

Regards.

Giorgio
7 REPLIES 7
klaasdc
Associate II
Posted on September 05, 2012 at 08:46

Hmm, don't see anything wrong with the code.

But to have period 10000 I would use a counter value of 9999. Not that this would make a big difference here.

Also, do you clear the timer's interrupt flag on entering your interrupt routine?

jheilig999
Associate II
Posted on September 06, 2012 at 11:41

Yes, 10000 to 999 doesn't make a big difference. To achieve the required timing I must set counter to 755.

Of course, I cleared the TIM3_IT_UPDATE into the handler:

#ifdef _COSMIC_

@far @interrupt void TIM3_UPD_OVF_BRK_IRQHandler(void)

#else /* _RAISONANCE_ */

void TIM3_UPD_OVF_BRK_IRQHandler(void) interrupt 15

#endif /* _COSMIC_ */

{

  TIM3_ClearITPendingBit(TIM3_IT_UPDATE);

}

jheilig999
Associate II
Posted on September 07, 2012 at 15:15

Any ideas why this happens?

Shoud I consider it an harware bug?

Regards

klaasdc
Associate II
Posted on September 07, 2012 at 15:59

I think a hardware bug in the timers is unlikely.

Another thing that comes to mind, do you generate an event source update after configuring the timer? Otherwise it is not guaranteed that all values are correctly loaded.

with TIM3_GenerateEvent(TIM3_EVENTSOURCE_UPDATE)

jheilig999
Associate II
Posted on September 07, 2012 at 16:30

Well, if I observed a changed beahaviour ranging from 10000 to 755 with the counter it would mean the counter should be loaded correctly. Anyway I'll try.

jheilig999
Associate II
Posted on September 10, 2012 at 13:05

No changes even adding TIM3_GenerateEvent(TIM3_EVENTSOURCE_UPDATE) when timer is configured. Checked also the assembly produced by Raisonance compiler, seems to be ok (LDW issue mentioned on the reference):

              ; FUNCTION ?TIM3_TimeBaseInit (BEGIN)

              ; Register-parameter TIM3_Prescaler (A) is relocated (AUTO)

              ; Register YW is assigned to parameter TIM3_Period

              ; SOURCE LINE # 78

0000 51                                EXGW   X,Y

              ; SOURCE LINE # 82

0001 C7532A                            LD     0532AH,A

              ; SOURCE LINE # 84

0004 93                                LDW    X,Y

0005 9E                                LD     A,XH

0006 C7532B                            LD     0532BH,A

              ; SOURCE LINE # 85

0009 909F                              LD     A,YL

000B C7532C                            LD     0532CH,A

              ; SOURCE LINE # 86

000E 81                                RET    

klaasdc
Associate II
Posted on September 10, 2012 at 19:46

I tried your code with COSMIC and it worked first start. On a scope I get a nice 25 Hz (because of the WriteReverse)

int main(void) {

    u16 counter = 9999;

    /* Switch to 16Mhz Crystal Osc clock */

    CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, DISABLE);

    TIM3_DeInit();

    //counter = counter / 4 * 3; //correction to run closer to a 20 ms period

    TIM3_UpdateRequestConfig(TIM3_UPDATESOURCE_GLOBAL);

    TIM3_TimeBaseInit(TIM3_PRESCALER_32, counter);

    TIM3_UpdateDisableConfig(DISABLE);

    TIM3_ARRPreloadConfig(ENABLE);

    TIM3_ITConfig(TIM3_IT_UPDATE, ENABLE);

    TIM3_GenerateEvent(TIM3_EVENTSOURCE_UPDATE);

    // Enable TIM3.

    TIM3_Cmd(ENABLE);

        

    GPIO_DeInit(GPIOD);

    GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_SLOW);

    // Enable interrupts (no, really).

    enableInterrupts();

    // Infinite loop.

    while(1){

    }

}

//---------------------------------------------

@far @interrupt void Timer3_Interrupt_Handler(void) {

    GPIO_WriteReverse(GPIOD, GPIO_PIN_0);

    // Clear the interrupt pending bit

  TIM3_ClearITPendingBit(TIM3_IT_UPDATE);

}