Temporizador STM32F4 TIM2, llegando a 1 segundo

Estoy aprendiendo un poco sobre los temporizadores de propósito general en mi placa STM32F4Discovery y me gustaría saber cómo puedo configurar el temporizador para invocar una interrupción del temporizador cada segundo, o al menos hacer que el valor de recarga automática se restablezca a 0 cada 1 segundo.

Sé que la MCU funciona a 168 MHz y estoy usando el reloj interno como fuente de reloj TIM2. Me gustaría entender mejor cómo puedo calcular el valor de preescala, el período y la división de reloj apropiados para lograr 1 segundo.

TIM_HandleTypeDef timeBase;
timeBase.Instance = TIM2;
timeBase.Init.Prescaler = 0;
timeBase.Init.CounterMode = TIM_COUNTERMODE_UP;
timeBase.Init.Period = 168000000; // Hypothetical value (Period cannot be greater than 65535)
timeBase.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&timeBase);

¿Tengo razón al decir que lo anterior, con un preescalador de 0, un período de 168000000 y una división de reloj de 1 hará que el valor de recarga automática del temporizador se restablezca a 0 cada 1 segundo?

Ahora, el período tiene un valor máximo de 0xFFFF (65535), por lo que para mí eso significa que necesito manipular el valor del preescalador y el período para lograr un reinicio del valor de recarga automática de 1 segundo.

¿Hay una fórmula para hacer esto?

¿Está utilizando la biblioteca de periféricos STM32F4 de ST Micro, o el STM32CubeF4, o algo más? IIRC contiene código para configurar cada reloj del sistema y poner el temporizador en modo de recarga automática. Como ha calculado, debe manipular tanto el preescalador como el valor de recarga. 168 000 000 son aproximadamente 28 bits, por lo que dos factores (números), de aproximadamente 14 bits cada uno, funcionarían, o cualquier par con uno de 16 bits o menos y el otro de 12 bits o más, que multiplicados dan 168 000 000.

Respuestas (2)

Tienes dos problemas. La primera es que la MCU funciona a 168 MHz si se ha configurado de esa manera , y es posible que su compilador no lo haga de manera predeterminada. Configurar el reloj es un poco arcano. ST proporciona una herramienta basada en Excel para ayudarlo a crear un archivo de configuración, y luego el archivo debe colocarse en el lugar correcto y algunos otros archivos deben editarse.
ingrese la descripción de la imagen aquí

Recomiendo este sitio como un lugar para obtener toda la información relevante. Hay una página ST con instrucciones , pero no es tan clara como algunos de los otros tutoriales.

Si hace esto, el bus APB1, en el que está TIM2, funcionará a 42 MHz como máximo, lo que le dará un reloj TIM2 de 84 MHz (se duplica con PLL). Si necesita más rápido que eso, debe usar uno de los temporizadores en APB2, que va el doble de rápido. Tenga en cuenta que ese bus no tiene temporizadores de 32 bits.

ingrese la descripción de la imagen aquí

El segundo problema es que, como dijiste, excediste un valor máximo. Sí, necesitas jugar con los dos valores. Si divide su reloj por (42000-1) con el preescalar para obtener una base de tiempo de 2 kHz y luego establece el período en (2000-1), ahí está su intervalo de 1 segundo.

Por supuesto, debe ENCENDER EL RELOJ al periférico TIM2 y luego habilitar TIM2, o nada funcionará.

Gracias por la respuesta. Esto realmente ayudó mucho. Estoy usando CubeMX en lugar de la hoja de Excel para configurar mi proyecto, pero hace lo mismo.
¿Por qué estamos restando 1 de 42000 y 2000?
Porque comienza en cero e interrumpe en el desbordamiento
Eh, cierto. :) A veces vivo en un mundo de sueños. Gracias por eso.

Además, si no desea involucrarse en la configuración del reloj mediante registros RCC , puede agregar fácilmente las dos líneas siguientes a la función de inicio del temporizador:

// This idea has been taken from "USART BRR Configuration" section in the USART_Init() function

RCC_ClocksTypeDef   RCC_ClocksStatus;
RCC_GetClocksFreq(&RCC_ClocksStatus);/*This line gives us System current frequency
Note that above function returns the frequencies of different on chip clocks; SYSCLK, HCLK,  PCLK1 and PCLK2.*/

y luego para el Prescaler y Period tendrá:

/* timer_tick_frequency for TIM4 = ( (2*APB1 frequency)/10000 )-1 */

TIM_TimeBaseInitStructure.TIM_Prescaler = (2*RCC_ClocksStatus.PCLK1_Frequency/10000-1);//Conter clock frequency (CK_CNT) is now 10KHz

TIM_TimeBaseInitStructure.TIM_Period    = (10000-1);//Update Event occurs every 1 Seconds

Entonces, si supone que la frecuencia APB1 es de 42MHz, entonces el valor del Prescaler es:

(2*42000000)/10000 - 1 = 8400 -1 = 8399

luego puede pasar por el controlador IRQn cada 1 segundo para hacer lo que quiera.