Custom made delay function using TIM6 does not work as intended.
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
}