Skip to main content
Visitor II
December 15, 2016
Question

TIM4 weird results

  • December 15, 2016
  • 3 replies
  • 1904 views
Posted on December 15, 2016 at 19:47

Hello, I am using stm8s003f3 and I wanted to count with 1 ms of precision and it works well.

I use a prescaler of 128 and a period of 125 and if I use my delay function with 1000 as parameter, I get the second.

However if I use a prescaler of 16 and period of 1, normally I get 1 �s precision but my delay function with 1000000 is logically 1 second too but it's +- 7s

I don't know what I'm doing wrong so if someone can help me.

My main.c 

http://pastebin.com/TgheG5gf

stm8_interrupt_vector.c 

http://pastebin.com/izX7cEVU

Thanks !

#tim4 #timer
    This topic has been closed for replies.

    3 replies

    ST Employee
    December 15, 2016
    Posted on December 15, 2016 at 20:52

    Got an old code for STM8L151 related to delay implementation, in case it gives some clues...

    ////////////////////////////////////////////////////

    // These functions use TIM3 to measure elapsed time

    #define TIME_CHUNK 1000

    void NOPs(u16 loop) {

    while(loop--) _asm('nop\n');

    }

    void Wait_us(u32 time_us) {

    // the max time_us is 1000, if more than this, we slice it in 1000 pieces

    u32 delay;

    while(time_us) {

    if(time_us<5)

    time_us = 5; // smallest delay time allowed

    if(time_us>TIME_CHUNK)

    delay = TIME_CHUNK;

    else

    delay = time_us;

    Set_Countdown(delay);

    while(!Countdown_Over()) ;

    time_us = time_us - delay;

    }

    return;

    // Set_Countdown(time_us);

    // while(!Countdown_Over()) ;

    }

    void Wait_ms(u16 time_ms)

    {

    while(time_ms--)

    Wait_us(1000);

    }

    //~~~~ function body

    void Init_Countdown(void) {

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, ENABLE);

    TIM3_TimeBaseInit(TIM3_Prescaler_16,TIM3_CounterMode_Up, 65535 ); // make a 1us clock unit for timer

    TIM3_OC1Init(TIM3_OCMode_Timing,TIM3_OutputState_Disable,0x0000,TIM3_OCPolarity_High,TIM3_OCIdleState_Reset);

    // the second one is to measure in 50 msec unit

    TIM3_OC2Init(TIM3_OCMode_Timing,TIM3_OutputState_Disable,0x0000,TIM3_OCPolarity_High,TIM3_OCIdleState_Reset);

    TIM3_Cmd(ENABLE);

    Set_Countdown2(50000); // to start later the first tick

    }

    void Set_Countdown(u32 time_us) {

    u16 capture;

    //disableInterrupts();

    TIM3_ClearFlag(TIM3_FLAG_CC1);

    // start the timer and main loop will wait for flag

    capture = TIM3_GetCounter();

    // here put the conversion from us to timer_ticks

    TIM3_SetCompare1(capture + time_us);

    //enableInterrupts();

    }

    u8 Countdown_Over(void) {

    if (TIM3_GetFlagStatus(TIM3_FLAG_CC1) != RESET)

    {

    TIM3_ClearFlag(TIM3_FLAG_CC1);

    return TRUE;

    };

    return FALSE;

    }

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 50 msec version

    void Set_Countdown2(u32 time_us) {

    u16 capture;

    // Timer countdown is 'duration'

    if(time_us==0)

    return;

    // convert us to timer count : 1 us = 64 counts ==> 

    time_us = time_us * 1; //64; // before PLL was x16, now PLL is x9 (slowed down clock speed)

    // overflow at 65536 <=> 932 us, so we break down the total time by 500 us blocks

    TIM3_ClearFlag(TIM3_FLAG_CC2);

    // start the timer and main loop will wait for flag

    capture = TIM3_GetCounter();

    // here put the conversion from us to timer_ticks

    TIM3_SetCompare2(capture + time_us);

    }

    u8 Countdown2_Over(void) {

    if (TIM3_GetFlagStatus(TIM3_FLAG_CC2) != RESET)

    {

    TIM3_ClearFlag(TIM3_FLAG_CC2);

    return TRUE;

    };

    return FALSE;

    }

    u8 Poll_For_50msec_elapsed(void) {

    if(Countdown2_Over()==TRUE)

    {

    Set_Countdown2(50000); // 50 msec

    return TRUE;

    }

    return FALSE;

    }
    Visitor II
    December 16, 2016
    Posted on December 16, 2016 at 09:13

    Hello,

    Looking at this quickly I would imagine that with such a short period that the interrupt/other code could take longer than the period sometimes. Hence you miss a count or perhaps the interrupt re-triggers.

    Thanks,

    Ian

    ST Employee
    December 16, 2016
    Posted on December 16, 2016 at 09:58

    It is correct, this is an example when someone needs to do a timeout, which happens in specific cases.

    Visitor II
    December 22, 2016
    Posted on December 22, 2016 at 20:33

    Hello!

    Ian is right!

    usually stm8s003f3 has 16MHz clock frequency, so in 1 microsecond, the micro only has 16 clock cycles.

    with your code, micro have to leave main routin, save parameters in stack and enter interrupt routine, does what you want ( decrementing timer counter ) and then reload saved parameters and return back to main routine in only 16 clock cycles. it is not possible for it! so it takes longer time than what you expected.

    Usually in 16MHz clock speed micro controllers, by the method you used, we can not easily have one microsecond time precision.

    you can use direct hardware reaction for such limited time task, or in the way you are making time ticks, you can use larger time interrupts like 50us or more.

    cheers...

    Visitor II
    January 24, 2017
    Posted on January 24, 2017 at 01:24

    Thanks, now it seems logic why it wasn't working...