Recursos del PIC -Uso del TMR0 como contador

En este ejemplo, aprenderemos cómo utilizar el TIMER 0 con una frecuencia de reloj externa en un microcontrolador PIC. Utilizaremos la señal externa aplicada a la patilla RA4/TOCKI del PIC para generar una interrupción a través del TIMER 0 cada segundo. En la función de interrupción, implementaremos el código necesario para hacer parpadear un LED en la patilla RB7 del PIC.

Biblioman

4/1/20094 min read

Vamos a ver en este ejemplo como utilizar el TIMER 0 con una frecuencia de reloj externa al microcontrolador, la señal externa la aplicaremos, como no, a la patilla RA4/TOCKI del PIC, dicha señal la utilizaremos para generar una interrupción a través del TIMER0 cada segundo, en la función de interrupción implementaremos el código necesario para hacer parpadear un Led en la patilla RB7 del PIC.

La frecuencia de la señal de reloj externa que utilizaremos será de 400 Hz y el Timer 0 lo configuraremos para qué empiece a contar en el flanco de subida de la señal de reloj, el circuito que tenemos que implementar será el siguiente:

Bien, primeramente vamos a ver como se tiene que configurar el registro OPTION para que el TMR0 trabaje de esta forma:

Primeramente el bit TOCS tenemos que ponerlo a 1, recordar que:

  • Si TOCS=1, el TMR0 actúa como contador.

  • Si TOCS=0, el TMR0 actúa como temporizador

Luego vamos hacer nuestros cálculos, teniendo en cuenta que queremos tener una interrupción cada segundo, si os fijáis en la formula de abajo es parecida a la que vimos en el ejemplo anterior, a excepción de que la frecuencia de reloj externa no está multiplicada por 4. Al igual que antes elegimos un Prescaler, en este ejemplo 4 (podíamos a ver elegido otro cualquiera que estuviera en la tabla) y calculamos el valor con el que tenemos que inicializar el TMR0 para que se produzca su desbordamiento cada segundo.

Si despejamos el valor que tenemos que cargar en el TMR0 nos sale un valor de 156 que en hexadecimal es de 0x9C.
La función en C para configurar el TMR0 lógicamente es la misma que en el ejemplo anterior pero con parámetros diferentes:

setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_4);

Las palabras utilizadas para declarar los parámetros definen ya su significado. Pero para ver directamente lo que hace la función, podemos ejecutar el programa paso a paso, o poner un breakpoint en la línea siguiente a la instrucción de arriba, abrir la ventana de visualización de los registros internos del PIC que nos ofrece el entorno de Proteus y ver como queda el registro OPTION después de ejecutar la sentencia:

Como vemos en los registros del PIC, el bit 5 del registro OPTION está a 1 (reloj externo) y los bits PS2:PS0 tienen el valor 001 que corresponde a un preescaler de 1:4 que es el que habíamos elegido.

La señal de reloj externa la podemos simular por medio de Proteus, si seleccionamos Generator Mode -> DCLOCK nos saldrá una ventana que configuraremos según se muestra en la figura de abajo:

Si analizamos la tensión en el ánodo del Led mediante una gráfica, observamos que la señal cuadrada generada a partir de la interrupción en el pic tiene entre el flanco de subida y el flanco de bajada una diferencia en el tiempo de 1 s que es el valor que queríamos.

Si utilizáis el asistente para generar el esqueleto de la aplicación, tal como hicimos en el ejemplo anterior el timer hay que configurarlo de la siguiente forma:

Veis que sale un Overflow de 2.5 s, esto es lo que saldría en la formula si dejamos al TMR0 que empiece a contar desde 0.

El código del ejemplo será el siguiente:

#include <16F877A.h>

#fuses XT,NOWDT

#use delay(clock=4000000)

#bit RB7=0x6.7 //definimos RB7 como el pin 7 de la puerta B

#int_TIMER0 //la siguiente función tiene que ser la de interrupción del TMR0

void TIMER0_isr(void) //function interrupción TMR0

{

if (RB7==0)

{

RB7=1;

set_TIMER0(0x9C); //inicializa el timer0

}

else

{

RB7=0;

set_TIMER0(0x9C); //inicializa el timer0

}

}

void main()

{

setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_4);

enable_interrupts(INT_TIMER0);

enable_interrupts(GLOBAL);

set_tris_b(0b01111111); //configura RB7 como salida el resto como entrada

RB7=0; //inicializo el bit RB7 a 0;

set_TIMER0(0x9C); //inicializa el timer0

//el bucle infinito es necesario ya que si el micro entra en sleep

//desactiva la interrupción del TMR0

while(true);

}

Como veis no he utilizado el PIC 16F84 sino el 16F877A pero es exactamente igual lo único que hay que cambiar es la directiva #include<16f84.h> por #include <16f877A.h>. Microchip hace coincidir por compatibilidad las direcciones de memoria de los registros de los dispositivos de inferior categoría, de está manera con solo cambiar una línea de código podemos emigrar nuestra aplicación a otro PIC de mayor capacidad.

Bueno a lo mejor alguno piensa que para hacer parpadear un Led no hace falta tanta historia. Pero no se trata del que se hace, sino del como se hace, el contenido de la función de interrupción se puede cambiar por otro cualquiera según lo que queramos hacer en cada programa.

Una modificación que se podría hacer sería obtener la señal de reloj externa por medio de un circuito digital para poder implementar, si se quiere, el circuito en una placa.