AnsweredAssumed Answered

Timer at double expected speed (have considered clock tree)

Question asked by hon.bo_xuan on Oct 6, 2013
Latest reply on Oct 12, 2013 by Clive One
I'm using a DIY development board for STM32F405RGT6, with an 8MHz HSE. I've used the clock configuration tool from ST to generate the system_stm32f4xx.c file such that the clock is configured to 168MHz using the HSE. I've checked that the HSE value in the stm32f4xx.h file is correct.

Now I've configured TIM6 to generate an interrupt every (what I expected to be) 1 millisecond. TIM6 uses APB1, which has a prescaler of 4. Considering the clock tree, I expect the timer clock to be 84MHz. So I set my prescaler to 83, and period to 999.

By incrementing a volatile integer in the interrupt and blinking an LED based on that (no oscilloscope at home), I find the frequency to be twice of what I expected.

Here's the code I used to set up TIM6.

void base_timer_init(void) {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
 
    //TIM_TimeBaseInitStructure.TIM_Prescaler = 167;
    //TIM_TimeBaseInitStructure.TIM_Prescaler = (uint16_t)((SystemCoreClock/2)/1000000)-1;
    TIM_TimeBaseInitStructure.TIM_Prescaler = 83;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period = 999;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
 
    TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStructure);
 
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
 
    TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
 
    TIM_Cmd(TIM6, ENABLE);
}

And here's the code for blinking the LED:

#include <stdio.h>
 
#include "stm32f4xx.h"
#include "gpio.h"
#include "timer.h"
 
__IO uint32_t millis = 0;
 
int main(void) {
    RCC_HSEConfig(RCC_HSE_ON);
    while(!RCC_WaitForHSEStartUp());
 
    gpio_init();
    base_timer_init();
 
    while(1) {
        if (millis >= 1000) {
            millis = 0;
            GPIO_ToggleBits(GPIOC, GPIO_Pin_9);
        }
    }
    return 0;
}
 
void TIM6_DAC_IRQHandler(void) {
    millis++;
    TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
}

I've spent quite a few hours on this but made no progress, so I'll really appreciate any help!

Thank you in advance.

Outcomes