Temporizadores son una de las funciones mas usadas en microcontroladores y por esta razon es importante conocer como se pueden implimentar de una manera optimizada. La mayoria de compiladores para microcontroladores traen funciones para hacer temporizaciones por delay, pero estos interrunpen la ejecucion principal del programa y no son muy practicos.

Casi todos los proyectos electrónicos con microcontrolador hacen uso de los temporizadores para su funcionamiento. Una de las técnicas más comunes, es usar un Timer físico (TIM) del microcontrolador para generar una interrupción a cada milisegundo y a partir de esta interrupción, incrementar o decrementar contadores para generar los tiempos de los temporizadores. Este método tiene un inconveniente cuando el proyecto usa muchos temporizadores, pues la rutina de interrupción puede usar mucho tiempo de la CPU. Otra técnica es usar temporizadores por delay, pero estos tienen el inconveniente de no poder estar leyendo las entradas del microcontrolador mientras se esté ejecutando el delay. En este artículo describiremos como usar y codificar temporizadores dinámicos que eliminan los anteriores inconvenientes.

 

TEMPORIZADOES DINAMICOS

Este método usa solo un contador en la interrupción del timer físico (TIM) y a partir de este contador, generar todas las temporizaciones necesarias. El código presentado en este artículo puede ser adaptado a cualquier microcontrolador ARM de cualquier marca/fabricante o cualquier microcontrolador de 8/16 bits con buena memoria RAM. El código fuente presentado en este artículo, fue testado en el microcontrolador STM32L152RB, un ARM de 32 bit del fabricante ST. En la figura 1 podemos observar un diagrama de archivos fuentes para el código presentado en este artículo.

 

Figura 1
Figura 1

 

 

El código para la interrupción es el siguiente:

extern uint32_t systemTimer;

void TIM3_IRQHandler()

{

if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)

{

TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

 systemTimer++;

}

}

 

El código para este artículo usa el Timer 3 (TIM3) del microcontrolador, pero puede ser usado cualquier Timer que este configurado para ejecutar una interrupción a cada 1 milisegundo.

Ahora, se debe implementar un archivo SystemTimer.c que use el contador systemTimer. El código para el archivo seria:

#include "SystemTimer.h"

uint32_t systemTimer;

 

******************************************************************/

uint32_t SystemTimer_GetTime()

{

return systemTimer;

}

 

******************************************************************/

void SystemTimer_Init()

{

systemTimer = 0;

}

 

Este archivo fuente usa dos funciones: SystemTimer_GetTime() que retorna el valor del contador systemTimer y la función SystemTimer_Init() que inicializa el contador systemTimer a cero. Esta última función es llamada en el reset del microcontrolador.

 

El archivo cabecera SystemTimer.h seria:

 

uint32_t SystemTimer_GetTime(void);

void SystemTimer_Init(void);

 

Ahora, debemos implementar un archivo que use las funciones del archivo fuente SystemTimer.c, para crear los temporizadores dinámicos. A este archivo le podemos dar el nombre Timer.c y su código seria:

 

#include "Timer.h"

#include "SystemTimer.h"

 

******************************************************************/

uint32_t Timer_GetTime(Timer *p)

{

uint32_t systemTimer;

uint32_t timeSpan;

 

if(p->enabled == false)

return 0;

 

if(p->enabled != true)

return 0;

 

systemTimer = SystemTimer_GetTime();

 

if(systemTimer < p->startTime)

{

timeSpan = (0xFFFFFFFF - p->startTime) + systemTimer;

}

else

{

timeSpan = systemTime - p->startTimer;

}

 

return timeSpan;

}

 

******************************************************************/

void Timer_SetInterval(Timer *p, uint32_t interval)

{

p->interval = interval;

}

 

******************************************************************/

void Timer_Start(Timer *p)

{

p->startTime = SystemTimer_GetTime();

p->enabled = true;

}

 

******************************************************************/

void Timer_Stop(Timer *p)

{

p->enabled = false;

}

 

******************************************************************/

boolean Timer_Elapsed(Timer *p)

{

uint32_t timeSpan = Timer_GetTime(p);

 

if(timeSpan == 0)

return false;

 

if(timeSpan < p->interval)

return false;

 

Timer_Stop(p);

return true;

}

 

******************************************************************/

void Timer_Init(Timer *p, uint32_t interval)

{

p->startTime = 0;

p->interval = interval;

p->enabled = false;

}

 

La función Timer_Start() es usada para arrancar el Temporizador dinámico y la función Timer_Stop() es usada para parar el Temporizador. La función Timer_Init() es usada para inicializar el temporizador y es llamadas en el reset del microcontrolador.

La función Timer_SetInterval() es usada para programar el intervalo en microsegundos del Temporizador. Este intervalo también puede ser programado en la función Timer_Init().

Para saber cuándo el Temporizador llego a su tiempo programado, se usa la función Timer_Elapsed(), la cual retorna verdadero cuando el tiempo elapso. Para usar el Timer del sistema que creamos anteriormente con la interrupción del Timer físico 3 y el archivo fuente SystemTimer.c, usamos la función Timer_GetTime().

 

El archivo cabecera Timer.h seria:

 

typedef struct

{

uint32_t startTime;

uint32_t interval;

boolean enabled;

}Timer;

 

uint32_t Timer_GetTime(Timer *p);

void Timer_SetInterval(Timer *p, uint32_t interval);

void Timer_Start(Timer *p);

void Timer_Stop(Timer *p);

boolean Timer_Elapsed(Timer *p);

void Timer_Init(Timer *p, uint32_t interval);

 

La figura 2 muestra el diagrama en bloques de un hardware típico con microcontrolador, donde tenemos varias entradas y salidas. En la figura 3 podemos observar que usando estos temporizadores dinámicos, podemos leer las entradas y ejecutar las temporizaciones, sin detener el programa principal.

 

Figura 2
Figura 2

 

 

Figura 3
Figura 3

 

En el siguiente archivo fuente main.c, podemos ver cómo utilizar los temporizadores dinámicos.

#include "Timer.h"

 

Timer salida_1_Timer;

Timer salida_2_Timer;

Timer salida_3_Timer;

 

int main()

{

Init_IO();

 

Timer_Init(&salida_1_Timer, 3000);

Timer_Init(&salida_2_Timer, 1000);

Timer_Init(&salida_3_Timer, 200);

 

 

while(1)

{

if(Timer_Elapsed(&salida_1_Timer))

{

Toggle_Saladia_1();

}

 

if(Timer_Elapsed(&salida_2_Timer))

{

Toggle_Saladia_2();

}

 

if(Timer_Elapsed(&salida_3_Timer))

{

Toggle_Saladia_3();

}

}

}

 

En próximos artículos utilizaremos estos temporizadores dinámicos para ejemplos de proyectos con microcontroladores.

 

 

 

Buscador de Datasheets



N° de Componente