MICROCONTROLADORES
LABORATORIO
N° 07
Manejo
del Timer y las
Interrupciones.
I. CAPACIDAD
TERMINAL
●
Utilizar
al microcontrolador en aplicaciones de control electrónico.
●
Desarrollar
y ejecutar programas en un microcontrolador PIC
●
Programar
y configurar interfaces básicas del microcontrolador.
II. COMPETENCIA
ESPECIFICA DE LA SESION
●
Conocer
el funcionamiento y la configuración de las Interrupciones
●
Conocer
el funcionamiento y la configuración del Timer cero
●
Aplicar
estos conocimientos en la realización de un cronómetro.
- CONTENIDOS
A TRATAR
●
Interrupciones
●
Timer
cero.
IV. MATERIALES
Y EQUIPO
●
CCS
Compiler instalado.
●
Entrenador
de PICS
●
Pantalla
LCD
●
PIC16F877A
●
Guía
de Laboratorio. El trabajo se desarrolla de manera GRUPAL.
●
PC
con Software de simulación.
Timers:
Un timer no
es más que un contador cuya entrada está conectada al reloj del sistema. De
hecho, la mayoría de los timers pueden reconfigurarse como contadores. En ese
caso, en lugar de contar pulsos de reloj cuentan los pulsos que llegan a un
determinado pin.
Uso de
TIMERS con interrupciones (timer)
Tras
verificar que los TIMERS funcionan pasemos a usarlos en combinación con las
interrupciones para poder establecer tareas a intervalos regulares. Por
descontado, para poder usar interrupciones tenemos que habilitar las
interrupciones globales y la interrupción del TMR0 en particular (aunque esto
también se puede en la función OpenTimer con la máscara TIMER_INT_ON/OFF. Como
vimos en el tutorial de interrupciones es conveniente trabajar con macros para
no tener que recordar que bits habilitaban que interrupciones.
Ciertos
timers están considerados periféricos, por lo que también tendríamos que
habilitar las interrupciones periféricas, aunque no es el caso del TMR0.
El
fundamento del proceso es sencillo. La interrupción del TMR0 se producirá
cuando el contador del timer pase por cero (cada 256 o 65536 ciclos dependiendo
de si estamos en 8 o 16 bits). La idea es arrancar con un valor del contador
tal que en el tiempo deseado alcance el valor máximo (256 o 65536).
Consideremos
el modo 8 bits (sin divisor) y arranquemos con un valor 156 en TMR0L.
Necesitaremos 100 ciclos (256-156) para rebosar el contador y provocar la
interrupción. Al cabo de 100 x 0.2 usec = 20 usec se producirá la primera
interrupción.
El PIC
16F876A tiene un único vector de interrupción y todas las interrupciones que
ocurran provocan un salto que se dirija
ese vector, para este suceso la rutina de manejo de la interrupción debe
reconocer que evento o efecto
interrumpió el programa para ejecutar la rutina correcta.
Al
finalizar la rutina del ciclo de interrupción
(RETFIE) el programa retorna al punto donde fue interrumpido
Las
interrupciones permiten la interrupción del programa a cualquier suceso ya sea
de tipo interno o externa, la interrupción que se da en el PIC salta a la dirección del vector (0004h) de interrupción y ejecuta el ciclo
El PIC posee registros con flags de interrupción los cuales les permiten identificar el evento.
TEMPORIZADOR
En este
caso los temporizadores etarana referidos en base al PIC 16F876A:
El PIC
16F876A dispone de tres temporizadores/contadores:
Timer 0: 8 bits.
Timer 1: 16 bits.
Timer 2: 16 bits.
Pueden
funcionar como contadores de flancos externos o como temporizador (contador de
ciclos máquina)y disponen de “prescaler” para ampliar el tamaño de la cuenta
(hasta x256), ademas un temporizador posee una cuenta de 16 bits en dos
registros de 8 bits:
TMR1H (parte alta)
TMR1L (parte baja)
I.EVALUACIÓN
A partir del código
mostrado, realice los cambios necesarios para realizar un programa que CUENTE
EN FORMA DESCENDENTE, (temporizador regresivo), bajo las siguientes
condiciones:
-Al
presionar pulsador en D0, incrementar SEGUNDOS. el temporizador aún no debe
estar contando el tiempo. (sirve para configurar tiempo de cuenta).
-Al
presionar pulsador en D1, iniciar CUENTA REGRESIVA desde los minutos
previamente configurados.
-Si la cuenta llega a 00:00, congelar la
cuenta y sonar BIP 3 veces.
CODIGO
#include <16f877a.h> // Incluimos archivo con PIC a utilizar
#use delay (clock=20M) // Indicamos al compilador que trabajaremos a 20Mhz
#fuses HS, NOPROTECT, NOWDT // Configuración básica de los fusibles
#define LCD_ENABLE_PIN PIN_D3 //Definimos los pines a ser utilizados por la
#define LCD_RS_PIN PIN_D2 //pantalla LCD
#define LCD_RW_PIN PIN_A0
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c> // Incluimos librería para manejar Pantalla LCD
int centesimas=0,segundos=0,minutos=0;
INT encendido=0;
void BIP();
#int_TIMER0 // FUNCION DE INTERRUPCION POR
void TIMER(VOID) // DESBORDAMIENTO DEL TIMER 0
{
++centesimas; // incrementar una centésima
if (centesimas>99)
{
--segundos; // si llegamos a 100, incrementar un segundo
centesimas=0;
}
if (segundos==-1)
{
--minutos; // si llegamos a 60, incrementar un minuto
segundos=59;
}
if (minutos==-1) // si llegamos a 3 minutos, hacer alguna acción
{
minutos=0;
disable_interrupts (INT_TIMER0); //habilita interrupcion de timer0
// agregar cualquier otra acción necesaria.
}
set_timer0 (61); //reinicar cuenta desde 61
}
void main ()
{
lcd_init () ; // Inicializamos pantalla LCD
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //configuracion del timer0
set_timer0 (61); // interrupción cada centésima
//enable_interrupts (INT_TIMER0); //habilita interrupcion de timer0
enable_interrupts (GLOBAL); //todas las interrupciones activadas
printf (lcd_putc, "\f***Temporizador***") ; // Mandamos mensaje por única vez
WHILE (true)
{
lcd_gotoxy(2,2);
Printf(lcd_putc,"Tiempo %02u:%02u",minutos, segundos);
IF(!input(PIN_D0))
{
segundos = segundos + 1;
delay_ms(500);
}
IF(!input(PIN_E0))
{
minutos = minutos + 1;
delay_ms(500);
}
IF(!input(PIN_E2))
{
disable_interrupts (INT_TIMER0);
delay_ms(500);
}
IF(!input(PIN_D1))
{
enable_interrupts (INT_TIMER0);
encendido =1;
}
IF (minutos==0 && segundos==0 && encendido==1)
{
delay_ms(100);
BIP();
delay_ms(500);
BIP();
delay_ms(500);
BIP();
delay_ms(500);
minutos=0;
segundos=0;
encendido =0;
}
}
}
void BIP()
{
int i;
FOR (i=0;i<=50;++i)
{
output_high(PIN_E1);
delay_ms(1);
output_low(PIN_E1);
delay_ms(1);
}
}
CODIGO
#include <16f877a.h> // Incluimos archivo con PIC a utilizar
#use delay (clock=20M) // Indicamos al compilador que trabajaremos a 20Mhz
#fuses HS, NOPROTECT, NOWDT // Configuración básica de los fusibles
#define LCD_ENABLE_PIN PIN_D3 //Definimos los pines a ser utilizados por la
#define LCD_RS_PIN PIN_D2 //pantalla LCD
#define LCD_RW_PIN PIN_A0
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
#include <lcd.c> // Incluimos librería para manejar Pantalla LCD
int centesimas=0,segundos=0,minutos=0;
INT encendido=0;
void BIP();
#int_TIMER0 // FUNCION DE INTERRUPCION POR
void TIMER(VOID) // DESBORDAMIENTO DEL TIMER 0
{
++centesimas; // incrementar una centésima
if (centesimas>99)
{
--segundos; // si llegamos a 100, incrementar un segundo
centesimas=0;
}
if (segundos==-1)
{
--minutos; // si llegamos a 60, incrementar un minuto
segundos=59;
}
if (minutos==-1) // si llegamos a 3 minutos, hacer alguna acción
{
minutos=0;
disable_interrupts (INT_TIMER0); //habilita interrupcion de timer0
// agregar cualquier otra acción necesaria.
}
set_timer0 (61); //reinicar cuenta desde 61
}
void main ()
{
lcd_init () ; // Inicializamos pantalla LCD
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //configuracion del timer0
set_timer0 (61); // interrupción cada centésima
//enable_interrupts (INT_TIMER0); //habilita interrupcion de timer0
enable_interrupts (GLOBAL); //todas las interrupciones activadas
printf (lcd_putc, "\f***Temporizador***") ; // Mandamos mensaje por única vez
WHILE (true)
{
lcd_gotoxy(2,2);
Printf(lcd_putc,"Tiempo %02u:%02u",minutos, segundos);
IF(!input(PIN_D0))
{
segundos = segundos + 1;
delay_ms(500);
}
IF(!input(PIN_E0))
{
minutos = minutos + 1;
delay_ms(500);
}
IF(!input(PIN_E2))
{
disable_interrupts (INT_TIMER0);
delay_ms(500);
}
IF(!input(PIN_D1))
{
enable_interrupts (INT_TIMER0);
encendido =1;
}
IF (minutos==0 && segundos==0 && encendido==1)
{
delay_ms(100);
BIP();
delay_ms(500);
BIP();
delay_ms(500);
BIP();
delay_ms(500);
minutos=0;
segundos=0;
encendido =0;
}
}
}
void BIP()
{
int i;
FOR (i=0;i<=50;++i)
{
output_high(PIN_E1);
delay_ms(1);
output_low(PIN_E1);
delay_ms(1);
}
}
OBSERVACIONES
El registro TMR0 del timer0 en el PIC está formado por 8 bits por lo que se puede contar desde 0 hasta 255.
- Para generar los segundos, minutos y centésimas, debemos usar 3 variables de tipo entero
- Si queremos saber el tiempo de un segundo real debemos usar el timer 0 el cual es de 8 bits
- Si queremos parar el cronómetro, usamos la sentencia: “disable_interrups” y el pulsador en el pin A5 el cual también aumenta los minutos y para iniciarlo de nuevo: “enable_interrups” y el pulsador en el pin D0.
CONCLUSIONES
-Se
concluye que los Timer para los PICs tiene una amplia gama de aplicaciones en
la práctica. Sólo unos pocos programas no lo utilizan de alguna forma. Es muy
conveniente y fácil de utilizar en programas o subrutinas para generar pulsos de
duración arbitraria, en medir tiempo o en contar los pulsos externos (eventos)
casi sin limitaciones.
Para el caso de realizar un cronómetro con cuenta hacia atrás. Fue necesario asignar a la variable segundos 59 y terminarla en -1, igualmente con minutos.
Para el caso de realizar un cronómetro con cuenta hacia atrás. Fue necesario asignar a la variable segundos 59 y terminarla en -1, igualmente con minutos.
Revisado. No hay video
ResponderEliminar