Configuración de la tasa de interrupciones del temporizador para la placa de descubrimiento STM32F4xx

Estoy trabajando en un proyecto con la placa STM32F407 y Keil, y como parte de un proyecto más grande en el que estoy trabajando, necesito configurar una interrupción de temporizador. Eventualmente funcionará a alrededor de 46 kHz, pero por ahora solo estoy tratando de controlar la velocidad a la que interrumpe.

En su estado actual, tengo el temporizador y la interrupción funcionando, de modo que cuando TIM3 termina de contar su período, genera una interrupción para la que tengo un controlador escrito. Luego puedo hacer parpadear un LED o hacer lo que sea necesario en este controlador. Mi problema es que no importa cómo lo configure, no puedo ajustar la velocidad a la que interrumpe. He puesto un contador que incrementa cada vez que se lanza la interrupción. Usé esto para cronometrarlo y descubrí que parece funcionar a una velocidad de aproximadamente 245 kHz (+/- tal vez 5 kHz).

He usado la hoja de cálculo de Excel que genera el archivo system_stm32f4xx para configurar un reloj de 168 MHz. Configuro el reloj TIM3 usando la siguiente función:

void InitializeTimer() {
    TIM_TimeBaseInitTypeDef SetupTimer;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    SetupTimer.TIM_Prescaler = 167-1;
    SetupTimer.TIM_Period = 1000-1;
    SetupTimer.TIM_CounterMode = TIM_CounterMode_Up;
    SetupTimer.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseInit(TIM3, &SetupTimer);
    TIM_Cmd(TIM3, ENABLE); 
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
}

Configuro la interrupción con la siguiente función:

void EnableTimerInterrupt()
{
    NVIC_InitTypeDef nvicStructure;
    nvicStructure.NVIC_IRQChannel = TIM3_IRQn;
    nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;
    nvicStructure.NVIC_IRQChannelSubPriority = 1;
    nvicStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvicStructure);
}

Ambos son llamados desde main en este orden. Según esta publicación, encontré los valores preescalares y de período anteriores para obtener una interrupción de 1 kHz. Sin embargo, éste no es el caso. Sin ningún orden en particular, una lista de cosas que he probado incluye:

  • Numerosas combinaciones diferentes de valores preescalares/períodos
  • Cambiando el HSE_VALUE en stm32f4xx.h de 25 MHz a 8 MHz (todo lo que he visto dice que el oscilador externo funciona a 8 MHz, no a 25; pero eso es lo que el archivo de Excel configuró para
  • agregando lo siguiente a mi función de inicialización del temporizador:

    uint16_t prescalar_val = (uint16_t) ((SystemCoreClock / 2) / 6000000) - 1; //6 MHz
    ...
    TIM_PrescalerConfig(TIM3, prescalar_val, TIM_PSCReloadMode_Immediate);
    

    Que es un fragmento de código que encontré que decía que configura el temporizador para que se ejecute a 6 MHz

Estoy bastante perplejo en este punto. He leído la sección de este documento sobre temporizadores de uso general (capítulo 18) y, según ese y otros ejemplos que encontré en línea, estoy haciendo todo bien. Tal vez hay algo que me estoy perdiendo, lo que no sería muy sorprendente: soy bastante nuevo en esto. En el peor de los casos, solo uso la interrupción tal como está, y uso un contador para dividir la frecuencia, pero parece una solución bastante tonta.

Cualquier ayuda que alguien pudiera darme sería muy apreciada. Si alguien quiere mirar cualquier otro archivo o función en particular, puedo publicarlo.

Respuestas (1)

Entonces, después de mucha frustración, descubrí cómo escalar mi temporizador/interrupción. Estaba tratando de hacerlo todo a la vez en lugar de desarrollarlo gradualmente.

En caso de que alguien encuentre esta pregunta, encontré este artículo y seguí sus instrucciones paso a paso: configurar el temporizador, luego la interrupción y luego el controlador de interrupciones. Creo que mi problema fue que no estaba borrando el bit pendiente después de cada interrupción, como lo hacen en el paso 9:

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

Agregar eso al final de mis controladores de interrupción pareció funcionar. Puedo escalar el tiempo como lo esperaría al proporcionar argumentos variables al preescalar y al período.