cancel
Showing results for 
Search instead for 
Did you mean: 

Custom made delay function using TIM6 does not work as intended.

AAnth.1
Senior

Hi

I am currently trying to create a delay function on my STM32F407 discovery board using a free running timer (I used TIM6 for this purpose). I set my counter clock frequency as high as possible and my max counter value to 0xFFFF. Based on my calculations, I should get a delay of approx 4ms:

16MHz/1=16MHz counter clock frequency -> 1/16MHz = 62.5ns counter period.

62.5ns*0xFFFF = 62.5ns*65535=0.0040959375s = 0.004s=4ms.

I toggle an LED every time the counter has reached its max value of 0xFFFF. So in theory, it should be 4ms on, 4ms off. 8ms in total.

However, using a logic analyzer, I get a period of 45ms, so a factor of 5 higher. Do you have an idea what could cause this behavior? Thank you,

#include "stm32f4xx.h"
 
#define LCD_BOOTUP_MS 15
 
void funcTimerInit();
void delay_LCD(int delay);
void funcGPIOInit();
 
int main(void)
{
	funcTimerInit();
	funcGPIOInit();
 
	for(;;)
	{
		delay_LCD(LCD_BOOTUP_MS);
	}
 
}
 
void funcTimerInit()
{
	// TIM6 setup
	// Peripheral clock
	RCC->APB1ENR |= (1<<4);	// Enables APB1 bus to use Timer 6
	// 2. Init timer
	TIM6->CR1 |= (1<<0);	// CEN: Enables counter
	TIM6->CR1 &= ~(1<<1);	// UDIS: Update event enabled
	TIM6->CR1 |= (1<<2);	// URS: Update request source enabled for overflow/underflow only
	TIM6->CR1 &= ~(1<<3);	// OPM: One Pulse Mode. Counter continues counting.
	TIM6->DIER &= ~(1<<0);	// UIE: Update interrupt disabled
	TIM6->EGR |= (1<<0);	// UG: Update generation. Re-initializes the counter and updates registers
	TIM6->PSC = 0x0000;		// Sets prescaler to 0. Timer clock is now 16MHz/(0+1)=16MHz -> 62.5ns
	TIM6->ARR = 0xFFFF;		// Counter goes up to 65535
}
 
void delay_LCD(int delay)
{
	static uint8_t flag = 1;
	if(delay==15)	// ms
	{
			while((TIM6->CNT) < 0xFFFF)
			{
				// Do nothing
			}
	}
	else
	{
		// Do something
	}
 
	if(flag)
	{
		// Turn LED on
		GPIOD->ODR |= (1<<12);		// Sets PD12
		flag = 0;
	}
	else
	{
		// Turn LED off
		GPIOD->ODR &= ~(1<<12);		// Clears PD12
		flag = 1;
	}
}
 
void funcGPIOInit()
{
	// Peripheral clock
	RCC->AHB1ENR |= (1<<3);	// Enables AHB1 to use GPIOD peripheral
	// 2. Init GPIO
	GPIOD->MODER |= (1<<24);	// Sets GPIOD as Output
	GPIOD->MODER &= ~(1<<25);	// Sets GPIOD as Output (redundant because bit 25 is already 0 after reset)
	GPIOD->OTYPER &= ~(1<<12);	// Set PD12 as Push Pull
	GPIOD->OSPEEDR &= ~(1<<24); // Sets speed on PD12 to low
	GPIOD->OSPEEDR &= ~(1<<25); // Sets speed on PD12 to low
}

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru
			while((TIM6->CNT) < 0xFFFF)
			{
				// Do nothing
			}

Since CNT goes from 0xFFFF to 0 in 1 tick, you may miss out on getting the exact value of 0xFFFF. Sounds like this is happening 5 times before you catch the actual value. One option would be to compare against 0xFFF0, so you at least have a larger span of ticks to capture. A better solution would be to use the timer in one shot mode and wait until it's done. Another would be to use SysTick for these types of measurements, or the debug timer.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

2 REPLIES 2
TDK
Guru
			while((TIM6->CNT) < 0xFFFF)
			{
				// Do nothing
			}

Since CNT goes from 0xFFFF to 0 in 1 tick, you may miss out on getting the exact value of 0xFFFF. Sounds like this is happening 5 times before you catch the actual value. One option would be to compare against 0xFFF0, so you at least have a larger span of ticks to capture. A better solution would be to use the timer in one shot mode and wait until it's done. Another would be to use SysTick for these types of measurements, or the debug timer.

If you feel a post has answered your question, please click "Accept as Solution".

Thank you for your reply. One shot mode did the trick. Regarding SysTick, I didn't know about it until I read your comment. I checked the reference manual, but didn't find it there, until Google eventually told me to find it in CMSIS.

Thanks a lot.

Cheers,