cancel
Showing results for 
Search instead for 
Did you mean: 

TIM4 weird results

Jérémy Moffa
Associate II
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
6 REPLIES 6
Seb
ST Employee
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;

}
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

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.

Posted on December 16, 2016 at 10:05

Hi Seb,

Sorry this is the first time I've used the new forum setup. My reply was intended for Jeremy, I hadn't looked at your example.

Thanks,

Ian

abbas
Associate II
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...

Jérémy Moffa
Associate II
Posted on January 24, 2017 at 01:24

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