2016-12-15 10:47 AM
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
stm8_interrupt_vector.c
Thanks !
#tim4 #timer2016-12-15 11:52 AM
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 allowedif(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;}2016-12-16 01:13 AM
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
2016-12-16 01:58 AM
It is correct, this is an example when someone needs to do a timeout, which happens in specific cases.
2016-12-16 02:05 AM
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
2016-12-22 11:33 AM
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...
2017-01-23 04:24 PM
Thanks, now it seems logic why it wasn't working...