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?
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.
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.
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á.
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.
gbulmer