Está en la página 1de 5

Laboratorio de temporizadores (TMR0)

Resumen — Se realizó un reloj digital compuesto por una estos pines son identificados como TxCKI donde x es el
pantalla LCD 16x2, interruptores que permiten al usuario setear número temporizador contador PIC que será usado como
la hora del reloj, y un microcontrolador PIC16F877A que por contador.
medio del desbordamiento del temporizador TMR0 e
implementando una respectiva ecuación para calcular el tiempo El PIC16F877A tiene 3 temporizadores que son llamados
entre interrupciones se hace un preciso control en incremento de
timer0, timer1 y timer2, el tiempo que tarda el temporizador
los segundos con respecto a la vida real.
contador PIC en aumentar su valor de unidad en unidad, se
puede modificar por programa mediante el uso de prescalers,
Palabras clave — TMR0, Preescaler, Desbordamiento de
TIMER, Reloj digital. siendo de esta manera más provechoso.

I. OBJETIVOS El registro en los microcontroladores PIC donde se guardan


y realizan los aumentos de uno en uno del temporizador PIC,
es llamado registro temporizador contador y es representado
● Implementar un reloj digital en XC8, donde el tiempo por TMRx, donde x es el número de temporizador contador
dependa del TMR0 del PIC16F877A. En el cual se PIC que puede ser 0, 1 2, dependiendo del número de
permita al usuario la configuración del tiempo. temporizadores con que cuente el microcontrolador PIC; el
● Hacer uso de las interrupciones ocasionadas por el temporizador contador PIC puede ser de 8 bits o de 16 bits.
TMR0 en el microcontrolador PIC16F877A.
● Aplicar la ecuación definida para determinar el El timer0 PIC es un temporizador contador de 8 bits, el
tiempo que tarda el TMR0 en desbordarse. registro TMR0 es el temporizador contador timer0 en sí, es
donde se guardan los valores del timer0 PIC, cuando es
utilizado como temporizador sus valores aumentaron de uno
II. INTRODUCCIÓN en uno entre 0 y 255 con cada 4 ciclos de reloj. Este registró
Un temporizador contador PIC es un registro que aumenta puede ser leído y escrito, además ser prescalado para que el
su valor en una unidad con cada 4 ciclos de reloj al cual se tiempo en su incremento de valor en una unidad sea mayor,
encuentre funcionando el microcontrolador PIC. el timer0 PIC cuando alcanza su valor máximo de 255 se
reinicia, volviendo a incrementar sus valores de 0 a 255,
El temporizador contador PIC es utilizado para obtener además cuando llega a su valor máximo y se reinicia puede
medidas de tiempos muy precisas, de ahí que se le da el producir una interrupción, lo que se decide por programa.
nombre de temporizador, en este caso el temporizador
contador PIC funciona con el reloj del sistema; pero también El temporizador contador pic TMR0 cuenta con lo que se
puede ser utilizado para realizar conteos, por lo que también conoce como prescaler esto hace que la frecuencia de trabajo
se le llama contador, en este caso el temporizador contador FOSC se divida por este prescaler, con lo que se logra que el
PIC ya no aumenta su valor de uno en uno en cada ciclo de temporizador contador pic tarde un poco más en aumentar su
trabajo, sino que lo hará mediante el flanco de subida o el valor en una unidad; el prescaler del timer0 PIC para el
flanco de bajada de alguna señal que llegue a un pin del PIC, PIC16F877A puede tomar el valor de 1, 2, 4, 8, 16, 32, 64,
128 o 256; estos valores se eligen mediante las ● Potenciómetro de 5K
combinaciones de los bits 0, 1 y 2 del
registro OPTION_REG. Instrumentos:

● Fuente de alimentación DC
La figura 1 muestra los valores que hay que asignar a estos ● Multímetro
bits para obtener los diferentes valores de los prescaler para
el timer0 PIC. Se realizó la implementación (Fig.3) y programación
necesarias para lograr la visualización de un reloj digital en
una pantalla LCD 16x2, este está regulado por las
interrupciones generadas por el temporizador TMR0 del
PIC16F877A, el cual se logró con el código que se muestra a
continuación este código incluye una librería (Header)
utilizada para la LCD.

Fig.1. Configuración de el registró OPTION_REG.

Al utilizar los prescaler se tiene la ventaja de


temporizar tiempos más largos, pero muchas veces se
vuelven demasiado largos si el registro TMR0 se inicia a 0, Fig.3. Simulación en proteus del reloj digital.
por lo que para temporizar tiempos que se quieren se debe
utilizar un prescaler adecuado e iniciar el registro TMR0 a Código de librería en XC8 para la LCD
un valor también adecuado.
#ifndef XC_HEADER_TEMPLATE_H
Utilizando una regla de 3 simple se llega a la siguiente #define XC_HEADER_TEMPLATE_H
ecuación que ayudará a encontrar el valor inicial adecuado a #include <xc.h> // include processor files - each processor file is guarded.
cargar en el registro TMR0 para obtener el tiempo buscado. //LCD Functions Developed by electroSome
[1] #define _XTAL_FREQ 4000000

#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
Fig.2. Valor adecuado para cargar en TMR0. #define D7 RD7
void Lcd_Port(char a)
{
III. PROCEDIMIENTO Y DATOS EXPERIMENTALES if(a & 1)
D4 = 1;
Materiales: else
D4 = 0;
● 1 microcontrolador (PIC16F877A) if(a & 2)
● Teclado matricial 4x4 D5 = 1;
● 3 pulsadores else
D5 = 0;
● 1 Cristales de cuarzo de 4 MHz
● 2 condensadores cerámicos de 15 pf if(a & 4)
● LCD 16x2 D6 = 1;
else EN = 1;
D6 = 0; __delay_us(40);
EN = 0;
if(a & 8) Lcd_Port(temp);
D7 = 1; EN = 1;
else __delay_us(40);
D7 = 0; EN = 0;
} }
void Lcd_Cmd(char a)
{ void lcd_putc(char *a)
RS = 0; // => RS = 0 {
Lcd_Port(a); int i;
EN = 1; // => E = 1 for(i=0;a[i]!='\0';i++)
__delay_ms(4); lcd_write_char(a[i]);
EN = 0; // => E = 0 }
}
void lcd_shift_right()
lcd_clear() {
{ Lcd_Cmd(0x01);
Lcd_Cmd(0); Lcd_Cmd(0x0C);
Lcd_Cmd(1); }
}
void lcd_shift_left()
void lcd_gotoxy(char a, char b) {
{ Lcd_Cmd(0x01);
char temp,z,y; Lcd_Cmd(0x08);
if(a == 1) }
{
temp = 0x80 + b - 1; // TODO Insert appropriate #include <>
z = temp>>4;
y = temp & 0x0F; // TODO Insert C++ class definitions if appropriate
Lcd_Cmd(z);
Lcd_Cmd(y); // TODO Insert declarations
}
else if(a == 2) // Comment a function and leverage automatic documentation with slash
{ star star
temp = 0xC0 + b - 1; /**
z = temp>>4; <p><b>Function prototype:</b></p>
y = temp & 0x0F;
Lcd_Cmd(z); <p><b>Summary:</b></p>
Lcd_Cmd(y);
} <p><b>Description:</b></p>
}
<p><b>Precondition:</b></p>
void lcd_init()
{ <p><b>Parameters:</b></p>
Lcd_Port(0x00);
__delay_ms(20); <p><b>Returns:</b></p>
Lcd_Cmd(0x03);
__delay_ms(5); <p><b>Example:</b></p>
Lcd_Cmd(0x03); <code>
__delay_ms(11);
Lcd_Cmd(0x03); </code>
/////////////////////////////////////////////////////
Lcd_Cmd(0x02); <p><b>Remarks:</b></p>
Lcd_Cmd(0x02); */
Lcd_Cmd(0x08); // TODO Insert declarations or function prototypes (right here) to leverage
Lcd_Cmd(0x00); // live documentation
Lcd_Cmd(0x0C);
Lcd_Cmd(0x00);
Lcd_Cmd(0x06);
} #endif /* XC_HEADER_TEMPLATE_H */

void lcd_write_char(char a)
{ Código XC8 para el reloj
char temp,y;
temp = a&0x0F; #pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
y = a&0xF0; #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT
RS = 1; // => RS = 1 enabled)
Lcd_Port(y>>4); //Data transfer #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT
disabled) lcd_gotoxy(2,1); //Ubicamos el cursor en fila2, columna 1
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR sprintf(arreglo_lcd," %d : %d : %d ",horas, minutos, segundos);
enabled) lcd_putc(arreglo_lcd); //Mostramos el valor de buffer_lcd
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit if(PORTBbits.RB5==0){
Serial Programming Enable bit (RB3/PGM pin has PGM function; horas++;
low-voltage programming enabled) __delay_ms(500);
#pragma config CPD = OFF // Data EEPROM Memory Code Protection if(horas==24){horas=0;}
bit (Data EEPROM code protection off) }
#pragma config WRT = OFF // Flash Program Memory Write Enable bits if(PORTBbits.RB6==0){
(Write protection off; all program memory may be written to by EECON minutos++;
control) __delay_ms(500);
#pragma config CP = OFF // Flash Program Memory Code Protection bit if(minutos==60){minutos=0;}
(Code protection off) }}
#define _XTAL_FREQ 4000000 if(y==0){
#include <xc.h> INTCONbits.GIE=1;
#include <stdio.h> //Incluimos stdio para escribir cadenas con formato lcd_gotoxy(1,1); //Ubicamos el cursor en fila 1, columna 1
en una variable lcd_putc("LA HORA ES: "); //mostramos una cadena de caracteres
#include "Lcd.h" //Incluimos la libreria LCD en la pantalla LCD
int horas=0,minutos=0, segundos=0,x=0,y=0,z=0; lcd_gotoxy(2,1); //Ubicamos el cursor en fila2, columna 1
char arreglo_lcd[20]; sprintf(arreglo_lcd," %d : %d : %d ",horas, minutos, segundos);
void main(void){ lcd_putc(arreglo_lcd); //Mostramos el valor de buffer_lcd
z=0;
}}}
TRISD=0;
TRISC=0; void __interrupt() pinb()//Función de interrupción
TRISBbits.TRISB4=1;//Pin 4 del Puerto B como entrada {
TRISBbits.TRISB0=0;//Pin 0 del Puerto B como salida if(INTCONbits.TMR0IF==1)//Si RBIF==1
PORTBbits.RB0=0;//RB0=0 {
TRISCbits.TRISC4=0;//Pin 4 del Puerto C como salida int a;//Variable con puerto B, requisito de Fabricante
PORTCbits.RC4=0;//RC4=0 a=PORTB;
INTCON=0;//Limpio registro INTCON x++;
INTCONbits.GIE=1;//Habilitación global de Interrupciones?? TMR0=61;
//INTCONbits.RBIE=1;//Habilitación de interrupciones por el puerto B if (x==20) {
INTCONbits.RBIF=0;//Bit de interrupción a 0 segundos=segundos+1;
INTCONbits.TMR0IE=1;//Permiso de interrupción por tmr0 x=0;}
lcd_init();
INTCONbits.TMR0IF=0;//RBIF a cero
OPTION_REG=0b00000111;//timer0 pic como temporizador, prescaler 256 }
//OPTION_REGbits.nRBPU=0;// Habilitación de resistencias de Pull-Up }
TMR0=61;//El timer0 PIC se inicia a 60 para temporizar 50ms

PORTBbits.RB0=0;
Este código permite un conteo que parte desde un preescaler
while(1){ de 256, El cual está dado por la configuración de los bit 0,1 y
if (segundos==60){segundos=0;minutos++; 2 del registro OPTION_REG, los cuales son: 111. Para
lcd_clear;}
obtener el tiempo requerido se usa la ecuación de la Fig.2, la
if(minutos==60){horas++;minutos=0;
lcd_clear; cual permite obtener un valor adecuado el cual se debe igualar
} al TMR0 para que cuando este llegue a 255 haya transcurrido
if (horas==24){horas=0; el tiempo que se requiere, el cual para este caso fue de 50 ms
lcd_clear;
} (Tretardo).
if(PORTBbits.RB4==0)
{z++; 8 0.050𝑠*4000000 𝐻𝑧
if(z==1){
𝑇𝑀𝑅0 = 2 − 4*256
−1
lcd_clear(); 𝑇𝑀𝑅0 ≈ 61
y=1;
INTCONbits.GIE=0;
Considerando que el tiempo de temporización es de 50 ms y
horas=0;minutos=0; segundos=0;}
que el reloj está en relación a los segundos, se calcularon las
if(z==2){
y=0; veces que debía transcurrir 50 ms para que fuera un segundo,
z=0; sabiendo que 1000 ms es 1 segundo:
}
__delay_ms(500);
} 𝑥 = 1000/50
if(y==1){ 𝑥 = 20
lcd_gotoxy(1,1); //Ubicamos el cursor en fila 1, columna 1
lcd_putc("LA HORA ES: "); //mostramos una cadena de caracteres
Donde x son las veces que debe transcurrir 50 ms para que sea
en la pantalla LCD un segundo. Por lo tanto cada que x sea igual a veinte ha
pasado un segundo. ● No podrían hacerse más de una interrupción, ya que
en programación no podría establecerse la prioridad
Cada que el TMR0 llega a 255 se realiza una interrupción por de la misma.
desbordamiento del temporizador, donde se realiza un
incremento de la variable x, la cual cuando sea 20 va a
incrementar otra variable denominada “segundos” y cuando REFERENCIAS
esta sea 60 va a incrementar otra denominada “minutos” y
[1] A. Machado, Temporizador / Contador PIC [En Línea]. 2021,11,
finalmente cuando minutos sea 60, “horas” se incrementará. 12.Disponible en:
Esto se logró con una serie de if 's que se muestra en el código https://es.scribd.com/presentation/461391336/TEMPORIZADO
R-CONTADOR-PIC.
del reloj, adicionalmente se puso otro para que no pase de 24
horas.

A fin de configurar la hora del reloj se adicionaron otra serie


de condiciones donde cuando se presiona una vez el pulsador
del set (RB4) la pantalla LCD mostrará un reinicio del tiempo,
visualizando 00:00:00, si se oprime el pulsador en el pin RB6
se aumentará la sección de minutos, mientras que si es
oprimido el pulsador conectado al pin RB5 las horas son las
que se incrementan.

IV. INTERPRETACIÓN DE LOS RESULTADOS

● En caso de que se deseara contar un segundo con el


TMR0 no se podría, ya que, este tiempo supera el
valor máximo del mismo, aun cuando el preescaler
sea el máximo. El tiempo del TMR0 está dado por:

𝑇𝑡𝑒𝑚𝑝 = (4 * 𝑝𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟)/(𝐹𝑂𝑆𝐶)
𝑇𝑡𝑒𝑚𝑝 = (4 * 256)/(4𝑀ℎ𝑧)
−6
𝑇𝑡𝑒𝑚𝑝 = 256𝑥10 𝑠

Donde Ttemp es el incremento por unidad del TMR0


por lo que aun si este empezará el 0 mientras
incrementa 255 veces el tiempo solo sería de 65.28
ms.

V. CONCLUSIONES

● El tiempo en Proteus es diferente al observado en la


práctica, ya que en la simulación no se podía
comparar el tiempo con un cronómetro, mientras que
en el montaje físico si.

● Considerando que el tamaño del registro TMR0 es de


8 bits, el tiempo máximo que permite temporizar es
de 65.28 ms, por lo que no se puede realizar un
conteo superior a este.

● Cuando se aplica la ecuación del valor adecuado para


cargar en TMR0, se obtiene un valor muy acertado al
del cronómetro estandarizado, aun cuando esté valor
es redondeado.

También podría gustarte