Tutorial 2. Temporizadores (Timers) en Microcontroladores de la serie STM32F4.

Bienvenidos a este tutorial donde utilizaremos uno de los 14 Timers con los que cuenta el microcontrolador en Ophyra. Estos Timers están divididos en 12 Timers de 16 bits y 2 Timers de 32 bits. Nuestro objetivo consistirá en prender y apagar un LED cada medio segundo. Una aplicación muy común para los Timers es como contador y contará hasta llegar a un número que se reiniciará al llegar al máximo configurado, provocando una interrupción donde ejecuta cierto código.

Configurar Hardware usando STM32CubeMX

Creamos un nuevo proyecto dentro de STM32CubeMX accionando sobre el icono correspondiente y seleccionando nuestro Microcontrolador STM32F407VGT6, ver imagen 1 e imagen 2.

Imagen 1. STM32CubeMX

Imagen 2. Selección del Microcontrolador

Una vez creado el proyecto (puedes ver un poco más de detalles en nuestro primer tutorial), del lado izquierdo podemos encontrar los 14 Timer y, accionando sobre uno de ellos, se muestran opciones de sus modos de operación, imagen 3.

Imagen 3. Modos de operación en un Timer

Algunos Timers cuentan con canales que permiten tener múltiples señales generadas por un solo Timer. Como observamos en la imagen 4, dentro del Timer 3 (TIM3) contamos con 4 canales con la capacidad de ser utilizados como comparadores, modos de captura o como PWM (Modulación por Ancho de Pulso).

Imagen 4. Modos de operación del Timer 3

Para comenzar a trabajar con nuestro Timer solo basta con indicar la fuente del reloj interna, como se muestra en la imagen 5. Una vez seleccionado el Timer, el nombre debe de cambiar a color verde, indicando que está en uso.

Imagen 5. Configuración y habilitación del Timer

Ahora que tenemos configurado el Timer con el que deseamos trabajar, debemos indicar el puerto con el que estaremos interactuando y escogeremos uno de los tres colores del LED RGB con el que cuenta Ophyra ubicados en los pines PE0, PE1 y PE2.

Imagen 6. Puerto E1 como salida

En la configuración del reloj del sistema y de los módulos de Hardware, utilizaremos el valor que viene por defecto del software el cual es de 16MHz. Lo podemos observar en la pestaña “Clock Configuration” (Configuración de Reloj, Imagen 7)

Imagen 7. Configuración de Reloj

Pasaremos a la pestaña de configuración (Configuration) en donde proporcionaremos configuración complementaria para los recursos que hemos seleccionado, ver Imagen 8.

Imagen 8. Configuración complementaria de los recursos

Accionando en el botón para el Timer3 aparece una ventana como la de la imagen 9:

Imagen 9. Configuración del Timer

Para poder configurar los valores que se nos piden (Prescaler y Counter Period (periodo del contador)) requerimos de estas fórmulas:

PRIMERA FÓRMULA

1.- Ft = (Fc)/(P+1)

SEGUNDA FÓRMULA

2.- T=(1/Ft)(Cp+1)

donde:

Ft = Frecuencia del timer

 Fc = Frecuencia del reloj

P = Prescaler

Cp = Counter Period

T = Tiempo

Proponiendo una frecuencia deseada de 1KHz = 1000Hz y un tiempo de medio segundo para su desborde tenemos:

P = (Fc/Ft) – 1 ; P = (16000000/1000) – 1

P = 15999

Cp = [(T*Ft)] – 1; Cp = (500) – 1;

Cp = 499

Una vez que tenemos los valores necesarios solo resta colocarlos en nuestra ventana del Timer. Nota que la segunda opción (en medio de Prescaler y Counter Period) nos permite elegir si queremos que cuente ascendente o descendente: “Counter Mode”.

Imagen 10. Configuración del Timer

También podemos indicar si dividir la frecuencia interna del reloj, si trabajará en modo de maestro o esclavo y el evento que ejecuta cuando termina su cuenta. Por el momento sólo indicaremos que la cuenta sea ascendente y que el evento se actualice cada vez que hay un desborde por el Timer como se muestra en la imagen 10.

Usaremos interrupciones para saber cuando ha ocurrido un desborde, por lo que habilitaremos las interrupciones globales; de esta forma liberamos nuestro código de tener que hacer encuestas para saber si ha terminado de contar y para ello solo basta dirigirnos a la pestaña “NVIC Settings” dentro de la pestaña de configuración del Timer 3 y habilitar dicha casilla, ver imagen 11.

Imagen 11. Habilitación de Interrupciones globales

Ahroa configuraremos nuestro pin de salida como se hizo en el tutorial 1: Puertos de entrada/salida de propósito general (GPIO), ver imagen 12.

Imagen 12. Configuración del Pin E1

Estamos listos para exportar nuestro proyecto al IDE de Atollic: TrueSTUDIO, para ello basta con accionar el icono en forma de engrane que se debajo de la barra de menú e indicaremos el nombre de nuestro proyecto, su ubicación, el IDE que utilizaremos para programar nuestro Microcontrolador y los archivos .c y .h de los recursos seleccionados, imagenes  13 y 14. A diferencia del tutorial 1, esta vez haremos un par de archivos .c y .h por cáda módulo de hardware usado, por lo que esperaremos ver archivos independientes para la configuración de nuestros puertos y del timer en nuestro proyecto en TrueSTUDIO, como veremos más adelante.

Imagen 13. Configuración para generar proyecto para IDE

Imagen 14. Archivos que generará STM32CubeMx para IDE

Realizar programa en Atollic TrueSTUDIO

Una vez que se ha compilado el proyecto y hemos abierto AtollicTrueSTUDIO nos dirigimos a la carpeta Src y al archivo main.c

Figura 1-15. Archivos del proyecto TIM3

Si has trabajado con Eclipse será sencillo ubicar los lugares importantes de TrueSTUDIO ya que tienen una estructura similar. Dentro del archivo main.c tenemos una descripción del código proporcionada por Atollic, y, en a partir de la línea 34, tenemos las cabecera del programa, ver imagen 16.

Imagen 16. Cabeceras del Microcontrolador

Seguido tenemos las funciones que configuran la frecuencia a la que trabajará el ARM y la función de error, que es ejecutada en caso de que ocurriera un error con el Micro, imagen  17.

Imagen 17. Prototipos de funciones de configuración y manejo de errores

Debajo de estas funciones encontramos la función main, todo lo que se encuentre dentro de esta función sera ejecutado por nuestro Microcontrolador, a partir de la linea 63, ver imagen 18.

Imagen 18. Inicio de la función main

Si nos posicionamos dentro de cualquier función se muestra una pequeña ventana que contiene la descripción de la misma como se muestra en la imagen 19.

Imagen 19. Descripción de la función HAL_Init()

Esta función nos dice que es usada para inicializar la librería Hal, esta función debe ser la primera instrucción por ejecutar en el programa main, antes de llamar cualquier otra función. Esto se debe de hacer debido a que esta librería contiene todas las funciones sobre los recursos del Micro. La instrucción SystemClock_Config(); configura la frecuencia que defininos en el Software STM23CubeMX, la función MX_GPIO_Init() inicializa los puertos que seleccionamos, ya sean como entrada o como salida y la función MX_TIM3_Init() nos inicializa el Timer que elegimos

Esta última función sólo inicializa el recurso, es decir, configura y prepara el módulo, pero falta indicarle que comience a trabajar. Para poder indicarle que inicie, requerimos de la función HAL_TIM_Base_Start_IT(), ver imagen 20.

Imagen 20. Descripción de la función HAL_TIM_Base_Start_IT()

Como parámetro solo debemos ingresar la dirección en Hardware de nuestro Timer, esto se hace colocando el carácter & seguido del nombre que se ha definido. Esta variable se encuentra en el archivo tim.c, ver imagen 21.

Imagen 21. Archivo tim.c

En la linea 42 de la imagen 21,  encontramos la asignación a TIM_HandleTypeDef (parámetro de entrada de función HAL_TIM_Base_Start_IT()) y en la imagen 22 vemos el llamado de dicha función en main.c.

Entonces, la función HAL_TIM_Base_Start_IT() comienza o inicia el modo de interrupción que habilitamos desde STM32CubeMx.

Imagen 22. Inicio de Timer 3

Observe que no tenemos nada dentro del ciclo While(1) ya que con la instrucción colocada no hay necesidad de estar preguntando si ya ha terminado de contar el Timer o si existe algún desborde ya que de esta tarea se encargará la rutina de interrupción, para saber más de interrupciones puedes revisar nuestro documento técnico NVIC.

Uno de los archivos que nos generó STM32CubeMx al momento de haber indicado las interrupciones globales es stm32f4xx_it.c que contiene las interrupciones de los diferentes recursos del ARM. La función de interrupción del Timer se encuentra en la linea 190, ver imagen 23, en dicho archivo.

Imagen 23 Archivo de interrupciones

Esta función es llamada cada vez que termina de contar el Timer y no es necesario volver a iniciar el conteo ya que existe la instrucción HAL_TIM_IRQHandler(&htim3) que automáticamente es colocada por Atollic. Ahora debemos construir nuestra aplicación de encendido y apagado de LED en esta función usando la función TogglePin (imagen 24).

Imagen 24. Función para cambiar de estado el pin E1

Ya hemos configurado e indicado la acción que haremos cada vez que entramos a la función de interrupción generada por el Timer 3. Por ultimo resta compilar nuestro proyecto para que nos genere el archivo con la extensión HEX que será cargada a nuestra tarjeta Ophyra, para ello nos dirigimos al icono con un martillo o dentro del menú PROJECT → BUILD PROJECT, ver imagen 25.

Imagen 25. Compilación del proyecto

Cargar programa a nuestra tarjeta de Desarrollo Ophyra

El último paso es programar tu tarjeta Ophyra. Si nunca lo has hecho, sigue esta GUÍA.

Conclusiones

Hemos configurado y programado 2 nuevos recursos en Ophyra, Timer e Interrupciones y hemos desarrollado una aplicación básica para hacer la prueba con ambos.

Te sugerimos hacer ejercicios como contadores de 8 bits, generaciones de ondas cuadradas, y, junto con nuestros demás tutoriales, generar adquisición usando ADC con una frecuencia de muestreo fija. Además, puedes revisar nuestra sección de prácticas, donde podrás encontrar algunos ejercicios y sus códigos.

Si tienes alguna consulta o duda sobre este tutorial o referente a cualquier otro tema de Ophyra, contactanos a nuestro Foro.

Menú