cancel
Showing results for 
Search instead for 
Did you mean: 

STM322F0- Can timers be used to get precise timeout functionality?

GenuineDeveloper
Associate III

In my project, I want to implement a timeout feature. That is, the user sets the required time and then starts a process. The process then has to end after the set timeout value. Now, the problem is I am able to turn off the process after the set timeout value, but the time is not precise( verified with portable timer device). That is, if I set a timeout of 5 minutes, it sometimes reaches the set value by 4.40 mins or 5.10mins, randomly. What am I doing wrong here? How to prevent this to get close to precise time?

Details:

Device: STM32F051R8T6

Clock: 24 Mhz

Timer16 is configured to tick every 1 second(Prescaler = 24000, ARR = 999)

void Timer16_Init(void)
{
	TIM_TimeBaseInitTypeDef	Timer16_struct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16,ENABLE);
	Timer16_struct.TIM_Prescaler = 24000;
	Timer16_struct.TIM_CounterMode = TIM_CounterMode_Up;
	Timer16_struct.TIM_Period = 999;
	Timer16_struct.TIM_ClockDivision = TIM_CKD_DIV1;
	Timer16_struct.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM16, &Timer16_struct);
 
	// That last function caused the UIF flag to get set. Clear it.
	TIM_ClearITPendingBit(TIM16, TIM_IT_Update);
 
	// Configure so that the interrupt flag is only set upon overflow
	TIM_UpdateRequestConfig(TIM16, TIM_UpdateSource_Regular);
	TIM_Cmd(TIM16, ENABLE);
}
 
void EnableTimer16Interrupt(void)
{
	nvicStructure.NVIC_IRQChannel = TIM16_IRQn;
	nvicStructure.NVIC_IRQChannelPriority = 0;
	nvicStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&nvicStructure);
	NVIC_SetPriority(TIM16_IRQn,0);
	NVIC_EnableIRQ(TIM16_IRQn);
	TIM_ITConfig(TIM16, TIM_IT_Update, ENABLE);
}

5 REPLIES 5
Tilen MAJERLE
ST Employee

Hello RV,

what you are currently having is interrupt on every update event, that is, every 1 second is interrupt.

To be precise, interrupt is triggered later than every 1s, because your prescaler should be set to 23999.

Timer_tick_frequency = timer_input_freq / (prescaler + 1)

With your prescaler, your tick frequency is 1000Hz and with period set to 999, you have interrupt each second.

To get 5 minutes timeout, you would need to tick for 300 interrupts. Can you show us this part?

Best regards,

Tilen

As Tilen indicates the Period and Prescaler value should be N-1 form

If you can't get the interrupt to count off a uniform/consistent number of seconds you've got serious problems elsewhere in your code.

You'd have to be blocking interrupts, or failing to properly count them.

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

To get 5 minute interrupt, I am incrementing a 16 bit variable every second, inside timer IRQ handler, hence, when the value reaches 299 I consider it as timeout(of 5 seconds). Is this method right? or is there any better way around?

// Timer16 used for interrupting every 1 second
 
void TIM16_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM16,TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM16,TIM_IT_Update);
                if(bTimerBegin)                     // Flag to check if user initiated timeout
                {
		      SecondsCounter++;                            // 16 bit unsigned variable
		      if(SecondsCounter > 299)			    // 1s x 300 = 5 minutes
		      {
				cSecondsCounter1 = 0;               //Variable reset
				bTimeOut = 1;                             // Flag to indicate Timeout
                                bTimerBegin = 0;
		      }
                }
        }
}

"You'd have to be blocking interrupts, or failing to properly count them."

Please refer the interrupt handler part replied to Tilen, is the method correct?

Regarding blocking interrupts, this is a 1 second interrupt, far slower than other interrupts being used, how could I be still "blocking" the interrupt? By using the same priority or should I block other interrupts when ever this interrupt is generated to get precision? How do I prevent this?

@Tilen MAJERLE​ Is this the correct way ?