Entendiendo la configuración de un temporizador en un STM32F10x

2

Estoy tratando de entender cómo configurar correctamente el temporizador en un STM32F10x.

La placa se está ejecutando con un cristal externo de 16 MHz, y estoy usando el PLL:

/* PLLCLK = 16MHz / 2 * 9 = 72 MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_9);

por lo que el tablero está funcionando a 72Mhz. Estoy configurando el temporizador de la siguiente manera:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseInitTypeDef timerInitstructure;
timerInitstructure.TIM_Prescaler =72000-1;
timerInitstructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitstructure.TIM_Period=1;
timerInitstructure.TIM_ClockDivision = TIM_CKD_DIV1;
timerInitstructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&timerInitstructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3,ENABLE);

Para asegurarme de que establezco la frecuencia correcta, alterno un pin con la interrupción, pero cuando mido con el alcance, obtengo 2.784 kHz. ¿Alguien puede decirme por qué tengo esta frecuencia?

    
pregunta Engine

2 respuestas

3

Escribí una respuesta más larga, antes de darme cuenta de la solución simple. Incluyo la respuesta completa en caso de que sea útil.

La respuesta rápida: los valores pasados a la función TIM_TimeBaseInit () son solo de 16 bits, por lo que 69999 es un valor no válido. Deberá elegir el período y el preescalador para que ambos estén por debajo de 65536.

Sin embargo, hay un segundo problema, así que continúa leyendo :)

La respuesta detallada:

¿Parece que estás apuntando a un reloj de 1kHz (1 ms)?

Aquí está la ecuación básica, donde PSC es el preescalador y ARR es el período ("Registro de recarga automática"):

(PSC+1)(ARR+1) = (EventTime)(ClkFreq)

Para 1ms:

(PSC+1)(ARR+1) = (1ms)(72MHz) = 72000

Ahora, puedes elegir cualquier conjunto de valores para hacer esto verdadero, siempre y cuando no excedan los 16 bits cada uno. Yo elegí:

(PSC+1) = 2 y (ARR+1) = 36000 ,

que proporciona PSC = 1 y ARR = 35999 .

Luego termina de configurar el reloj como lo has hecho.

En tu caso, eliges ARR = 1 y PSC = 71999. Cambiando las ecuaciones:

EventTime = (PSC+1)(ARR+1)/ClkFreq

EventTime = (1+1)(71999+1)/72MHz = 2ms , que no es lo que estás buscando.

Por supuesto, esto tampoco es en realidad lo que está obteniendo, debido al problema mencionado anteriormente con el tamaño del prescaler.

Por cierto, como señala @ScottSeidman, a menudo el temporizador está configurado correctamente pero el reloj en sí no lo está. Los árboles del reloj son sorprendentemente complicados! Una forma de verificar los relojes es usar la función RCC_MCOConfig() (o ver el registro RCC_CFGR). Se pueden usar para enviar los relojes internos directamente al pin MCO.

¡Buena suerte!

    
respondido por el bitsmack
1

@Bitsmack ha dado una gran respuesta, sin embargo, hay otro parámetro en juego que no se ha mencionado: TIM_ClockDivision. Es simplemente el divisor de reloj de hardware que se encuentra entre el reloj y el contador, y tiene valores discretos de 1,2 o 4 si la memoria sirve. En el ejemplo del OP es 1 (TIM_CKD_DIV1). Entonces, si por alguna razón necesita traer ClkFreq a un rango donde pueda usar valores de 16 bits para PSC y / o ARR, este parámetro será útil. No tanto en este caso, pero si está tratando con núcleos en frecuencias de reloj más altas, entonces tal vez sea así. También si necesita una mayor duración del temporizador (período). Así que la fórmula de @bitsmack podría escribirse como:

(PSC+1)(ARR+1) = (EventTime)[(ClkFreq)/ClkDiv]

Una forma intuitiva de pensar en los temporizadores básicos es que la frecuencia del evento del temporizador (nota: no el tiempo del evento) es simplemente el reloj de entrada dividido por cada uno de estos parámetros:

EventFreq = ClkFreq/ClkDiv/(PSC+1)/(ARR+1), and
EventTime = 1/EventFreq

que nos lleva a la fórmula de bitsmack. Puede enmarcar su requerimiento ya sea como un requisito de intervalo de tiempo de evento (quiero un temporizador con un período de 1 ms), o como un requisito de frecuencia de evento (quiero una tasa de interrupción de 1 kHz), las cuales son atendidas por las fórmulas anteriores.

    
respondido por el Bedouin_man

Lea otras preguntas en las etiquetas