Tutorial x

6

Click here to load reader

Transcript of Tutorial x

Page 1: Tutorial x

TUTORIAL X OBJETIVOS

• Crear códigos en C de mayor complejidad.

• Atender interrupciones por desbordamiento del Timer2

• Realizar el Décimo Proyecto: Reloj de Tiempo real.

• Repasar y reafirmar los conceptos vistos hasta el momento. PROYECTO 10: Reloj de Tiempo real En este proyecto vamos a repasar varios de los conceptos vistos hasta ahora al usar el Timer1 para generar una base de tiempo precisa que permita hacer un reloj de formato HH:MM:SS y lo visualizaremos en una LCD, para lo cual habrá que usar conceptos vistos en la practica 4 de los displays 7 segmentos. Además veremos algo sobre Timer2 el tercer timer del PIC16F877a que por ahora no nos será muy útil sin ver los conocimientos del modulo CCP del PIC pero que vamos a necesitar mas adelante. El Timer2 es un modulo Temporizador de 8 bits del PIC16F877A, que cuenta de 0 a 255 y almacena tal valor en el registro TMR2. El timer2 tiene además un Prescaler (como el Timer0 y Timer1) y además un Postscaler. Tiene una única fuente de pulsos: la frecuencia interna = Fosc/4. Al igual que el Timer1 tiene opción de encendido/apagado. Este modulo tiene asociada una interrupción que ocurre por un pulso que sale del postscaler el cual cuenta número de desbordamientos del TMR2. El postcaler va de 1:1 a 1:16, así por ejemplo, sea postscaler = 1:7 Esto indica que por cada 7 desbordamientos del TMR2 postcaler activara la interrupción. Esto es muy diferente a lo que se tenía en TMR0 y TMR1 en cuanto a interrupciones y es una de las grandes diferencias entre Timers en el PIC. Tales opciones tienen sus respectivos registros de configuración. Veámoslos detalladamente:

• Registros asociados a Timer2

Page 2: Tutorial x

Veamos el registro T2CON que para Timer2 cumple la misma función que T1CON para Timer1 y a OPTION_REG para Timer0 Bit7: No implementado Bit6-3: TOUTPS3:TOUTPS0 (Timer2 Output Postscale Select bits) Selección de Postscaler 0000 = 1:1 postscaler

0001 = 1:2 postscaler 0010 = 1:3 postscaler

• • •

1111 = 1:16 postscaler Bit2: TMR2ON (Timer2 On bit) 1: Enciende Timer2 0: Apaga Timer2 Bit0-1: T2CKPS1:T2CKPS0 (Timer2 Clock Prescale Select bits) 00: Prescaler 1:1 01: prescaler 1:4 1X: Prescaler 1:16

La interrupción mencionada se habilita colocando en 1 los bits 6 y 7 del INTCON, además del bit 1 del PIE1 (TMR2IE). Asociada a esta interrupción está la bandera TMR2IF (bit 1 del registro PIR1) El funcionamiento del Prescaler es parecido al de los anteriores Timers. Por ejemplo para un Prescaler 1:4 por cada 4 pulsos de reloj interno ocurre un incremento del TMR2. Una de las desventajas del Timer2 es que después de que se desborde la primer vez el TMR2, que previamente cargamos con X valor, no hay manera de volverlo a cargar con el valor inicial que teníamos porque la bandera TMR2IF no denota el desbordamiento de TMR2 sino una acumulación de desbordamientos. Esto afecta las sencillas expresiones que antes teníamos para los Timer0 y Timer1 en cuanto a los delay que se generaban y el valor con el cual cargábamos el TMR2: Delay(ms) = [(256 – TMR2) + 256*(Postscaler - 1)]*1000*Prescaler*(4/Fosc) (1)

Despejando de esta expresión tenemos que: TMR2 = 256 + 256(Postscaler-1) – _Delay(ms)*Fosc_ (2)

Prescaler*1000*4

Con estas dos ecuaciones se opera de manera similar a Timer0 y Timer1, se introducen los parámetros y estos nos indican con cuanto hay que cargar el TMR2 y cuanto es el retardo que se genera para los datos dados.

Page 3: Tutorial x

Ahora bien, en cuanto al proyecto propuesto vamos a usar el Timer1 en modo contador para generar una base de tiempo de un segundo con el cristal externo de 32768 Hz conectado a RC0 y RC1 tal como en el tutorial anterior, además habrán 3 variables contadoras: de segundos, minutos y horas transcurridas. Los tres contadores se van a iniciar en 0 y cada que el Timer1 se desborde (cada segundo) el contador de segundos va a incrementarse hasta llegar a 60 en cuyo caso se incrementa el contador de minutos y el de segundos se pone en 0. Análogamente cuando los minutos sean 60 habrá incremento del contador de horas. Además cuando sean las 24:59:59 y pase un segundo el reloj se inicia en 00:00:00. Para visualizar los números en el lcd primero habrá que separar unidades de decenas en segundos, horas, y minutos. Se podría hacer uso de la función div_t x como en el tutorial 4 pero acá se hará lo mismo usando operaciones de división y resta. Veamos las ecuaciones generales para tal fin: Decenas = Numero/10; (3) Unidades = Numero - Decenas*10; (4) En estas expresiones Numero es de dos dígitos y la operación división solo devuelve enteros (en PICC) ya que Numero debe definirse como entero ya que se cumple que (X entero)/(Y entero) = (Z entero) El proyecto debe incluir los archivos delay.c, delay.h, Main.c, lcd.c, lcd.h Los 3 últimos mostrados a continuación y los 2 primeros iguales a los incluidos en la carpeta de simples del PICC. Nota: Para abrir el esquema de conexiones en EAGLE se necesita la librería abi-lcd.lbr. Para instalar esta librería se debe copiar ese archivo en la carpeta lbr del EAGLE en Archivos de programa y habilitarla en el panel de control del EAGLE antes de abrir el archivo Tutorial10.sch Codigo Main.c #include <PIC.H> #include <stdlib.h> #include "lcd.h" unsigned int CONTS=0, CONTM=0, CONTH=0, UnSeg=0, DecSeg=0, UnMin=0, DecMin=0, UnHor=0, DecHor=0, BAN=0; /*Declaración de Variables CONTS: Contador de segundos CONTM: Contador de Minutos

Page 4: Tutorial x

CONTH: Contador de Horas UnSeg: Unidades de CONTS DecSeg: Decenas de CONTS UnMin: Unidades de CONTM DecMin: Decenas de CONTM UnHor: Unidades de CONTH DecHor: Decenas de CONTH BAN: Bandera que le indica al led cuando debe actualizarse */ void interrupt inter(void) { TMR1H = 0x80; //Se inicia el TMR1 en 8000h TMR1L = 0x00; if (CONTS==59) { CONTS=0; if (CONTM==59) { CONTM=0; if (CONTH==24) CONTH=0; else CONTH=CONTH+1; } else CONTM=CONTM+1; } else CONTS=CONTS+1; DecSeg=CONTS/10; //Rutina que separa unidades-decenas UnSeg=CONTS-DecSeg*10; DecMin=CONTM/10; UnMin=CONTM-DecMin*10; DecHor=CONTH/10; UnHor=CONTH-DecHor*10; TMR1IF = 0; //Bandera de interrupción a 0 BAN=1; //Bandera de Visualización activada } void main(void) { //Configuración Puertos TRISC = 0b00000011; //Pines 0 y 1 como entradas de cristal TRISB = 0b00000000; //Puerto B como bus de datos de salida al lcd INTCON = 0b11000000; //Se habilita interrupciones globales y periféricas. TMR1H = 0x80; //Se inicia el TMR1 en 8000h TMR1L = 0x00; T1CON = 0b00001110; //Prescalador en 1:1 (T1CKPS1=0/T1CKPS0=0) //Se activa oscilador (T1OSCEN=1) //Se desactiva la sincronización (T1SYNC=1)

Page 5: Tutorial x

//Se selecciona como CONTADOR (TMR1CS=1) TMR1IE = 1; //Habilita int. por desbordamiento de TMR1 TMR1IF = 0; //Se desactiva la Bandera TMR1ON = 1; //Inicia el conteo el TMR1 lcd_init(); //Inicialización LCD lcd_clear(); //Limpiar LCD while(1) //Ciclo Infinito { if(BAN==1) // Si hay que habilitar actualización lcd entonces: { lcd_goto(0x3); //Ir al espacio 4 de la línea 1 del lcd lcd_putch(DecHor+0x30); //Se suma a 0x30 para que lcd_putch(UnHor+0x30); //coincidan los ASCII con los números lcd_putch(0b00111010); //ASCII del : lcd_putch(DecMin+0x30); lcd_putch(UnMin+0x30); lcd_putch(0b00111010); //ASCII del : lcd_putch(DecSeg+0x30); lcd_putch(UnSeg+0x30); BAN=0; //Desactivar actualización del lcd } //Fuera del if el PIC no hace nada } //Fin While }//Fin main

Page 6: Tutorial x

DIAGRAMA DE CONEXIONES