Skip to main content
GenuineDeveloper
Associate III
November 23, 2018
Question

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

  • November 23, 2018
  • 2 replies
  • 1783 views

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);
}

This topic has been closed for replies.

2 replies

Tilen MAJERLE
ST Employee
November 23, 2018

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

GenuineDeveloper
Associate III
December 1, 2018

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;
		 }
 }
 }
}

Tesla DeLorean
Guru
November 23, 2018

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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
GenuineDeveloper
Associate III
December 1, 2018

"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?