Skip to content

Instantly share code, notes, and snippets.

@jerivas
Last active December 24, 2015 01:19
Show Gist options
  • Save jerivas/6722687 to your computer and use it in GitHub Desktop.
Save jerivas/6722687 to your computer and use it in GitHub Desktop.
// Reloj digital configurable con dos alarmas
// Muestra la hora en minutos, segundos, horas e indicador am/pm en una LCD
// Cuenta con tres botones: selector de modo, ajuste de minutos y de segundos
// La alarma se activa por un minuto y no se puede desactivar
// Ángel Moreno
// David Escobar
// Eduardo Rivas
#include "p18f4550.h"
#include "xc.h"
#include "stdlib.h"
#include "lcd.h" //Incluir cabeceras para manejo de LCD
//Directivas para activar los bits de configuracion
#pragma config FOSC = INTOSCIO_EC //Oscilador Interno, Puerto A RA6 activo,
#pragma config WDT = OFF //Watchdog timer apagado
#pragma config PBADEN = OFF //Parte baja del puerto B digitales
#pragma config MCLRE = ON //MCLRE Disponible
#pragma config DEBUG = ON //Modo de depuracion disponible
#pragma config LVP = OFF //Fuente de ISCP apagada
#define t100ms CCP1IF //Pasaron 100ms
#define mode_btn INT0IF //Botón de selección de modo en RB0
#define min_btn INT1IF //Botón de incrementar minutos en RB1
#define hour_btn INT2IF //Botón de incrementar horas en RB2
#define alarm LATB4 //Alarma en RB4 (puede ser LED o buzzer)
//Prototipos de funciones
void print_time(char hour, char min, char sec, char am_pm);
//Variables globales
// Matriz de mensajes para cada modo
char msgs[][17] = {" RELOJ DIGITAL ", " CONFIG ALARMA 1", " CONFIG ALARMA 2"};
char pm[] = "P.M.", am[] = "A.M.";
char secs[] = {0, 0, 0}; //Los minutos de reloj, al1 y al2
char mins[] = {0, 0, 0}; //Los minutos de reloj, al1 y al2
char hours[] = {12, 6, 8}; //Las horas de reloj, al1 y al2
char am_pm[] = {0, 1, 0}; //El indicador am/pm de reloj, al1 y al2
char mode = 0; //Selector de modo. Reloj: 0, Al1: 1, Al2: 2
char display[2]; //Carga el dato a mostrar en la LCD
char count = 0; //Contador de uso interno para determinar base de tiempo
//Configuracion
void config() {
IRCF0 = 1; //configuracion del OSCCON F=8MHz
IRCF1 = 1;
IRCF2 = 1;
//Configuracion de interrupciones
IPEN = 1; //habilita la prioridad de las interrupciones
GIE = 1; //habilita la mascara global de interrupciones
PEIE = 1; //habilita interrupciones periféricas
//Configuracion del modo comparador (generacion de eventos)
T3CON = 0x00; //configura TMR1 como fuente de reloj para los modulos ccp1/3
CCP1M3 = 1; //genera una interrupcion al coincidir
CCP1M2 = 0;
CCP1M1 = 1;
CCP1M0 = 1;
CCPR1 = 25000; //Genera una interrupción cada 100ms
//Configuracion del comparador 1
CCP1IE = 1; //habilita ccp1 bit interrupcion
CCP1IP = 1; //habilita ccp1 bit de prioridad de la interrupcion
//Inicializacion de los puertos
ADCON1 = 0x0F; //Deshabilita el ADC
CMCON = 0x07; //Deshabilitar comparador
PORTB = 0; //Limpiar PORTB
LATE = 0; //Limpiar PORTE
LATD = 0; //Limpiar PORTD
TRISB = 0b00000111; //Parte baja de PORTB como entrada
TRISE = 0; //PORTE como salida
TRISD = 0; //PORTD como salida tambien
INTEDG0 = 0;
INTEDG1 = 0;
INTEDG2 = 0; //Botones activos flanco descendente
INT0IE = 1;
INT1IE = 1;
INT2IE = 1; //Habilitar interrupciones por botones
//Configuracion del Timer 1
//Inicializacion de parte alta y baja del registro de trabajo TMR1
TMR1 = 0; //Limpiar el registro de trabajo de TMR1
T1CON = 0b10110001; //Configurar y encender TIMER1
//Inicializacion de los perifericos externos
LCD_Inicializar(); //Inicializa la pantalla LCD
}
//Funcion principal que imprime constantemente el tiempo en el modo actual
void main() {
config();
while (1) {
LCD_Posicion(0, 0);
LCD_Cadena(msgs[mode]);
LCD_Posicion(0x02, 0x40);
print_time(hours[mode], mins[mode], secs[mode], am_pm[mode]);
}
}
//Rutinas de interrupcion
void interrupt service(void) {
GIE = 0; //Desactivar mascara global de interrupcion
if (t100ms) { //Han transcurrido 100ms en el Timer1
count++;
if (count == 10) {//Desbordamiento a 1 segundo
secs[0]++;
count = 0;
if (secs[0] == 60) { //Desbordamiento a 1 minuto
mins[0]++;
secs[0] = 0;
if (mins[0] == 60) { //Desbordamiento a 1 hora
hours[0]++;
mins[0] = 0;
if (hours[0] == 12) { //Indicador am/pm
am_pm[0] = !am_pm[0];
}
if (hours[0] == 13) { //12 horas en vez de 24
hours[0] = 1;
}
}
} //Cada segundo se verifica si es hora de sonar la alarma
if ((hours[0] == hours[1] && mins[0] == mins[1] && am_pm[0] == am_pm[1]) ||
(hours[0] == hours[2] && mins[0] == mins[2] && am_pm[0] == am_pm[2])) {
alarm = !alarm; //La alarma es un pulso de 1Hz
}
}
t100ms = 0; // Limpia la bandera de Match en el Timer1
}
if (mode_btn) { //Se ha presionado el botón de modo
if (mode == 2) { //Solo permitir 0, 1 ó 2
mode = 0;
} else {
mode++;
}
mode_btn = 0; //Limpiar la interrupción del botón de modo
}
if (min_btn) { //Se ha presionado el botón de minutos
if (mins[mode] == 59) {
mins[mode] = 0;
} else {
mins[mode]++;
}
min_btn = 0; //Limpiar la interrupción del botón de minutos
alarm = 0; //Poner la alarma en 0 para evitar dejarla en 1
}
if (hour_btn) { //Se ha presionado el botón de horas
if (hours[mode] == 11) {
am_pm[mode] = !am_pm[mode];
hours[mode]++;
} else if (hours[mode] == 12) {
hours[mode] = 1;
} else {
hours[mode]++;
}
hour_btn = 0; //Limpiar la interrupción del botón de horas
alarm = 0; //Poner la alarma en 0 para evitar dejarla en 1
}
GIE = 1; // habilita mascara global de interrupcion
return;
}
//Procedimiento que imprime el tiempo en la LCD
void print_time(char hour, char min, char sec, char am_pm) {
if (hour < 10) { //Rellenar con 0 si hour < 10
LCD_Caracter('0');
}
itoa(display, hour, 10); //Convertir las horas a ASCII
LCD_Cadena(display); //Mostrar las horas
LCD_Caracter(':'); //Mostrar 2 puntos
if (min < 10) { //Rellenar con 0 si min < 10
LCD_Caracter('0');
}
itoa(display, min, 10); //Convertir minutos a ASCII
LCD_Cadena(display); //Mostrar los minutos
LCD_Caracter(':'); //Mostrar 2 puntos
if (sec < 10) {
LCD_Caracter('0'); //Rellenar con 0 si sec < 10
}
itoa(display, sec, 10); //Convertir segundos a ASCII
LCD_Cadena(display); //Mostrar las segundos
LCD_Caracter(' '); //Mostrar un espacio
if (am_pm == 0) { //Mostrar el indicador am/pm adecuado
LCD_Cadena(am);
} else {
LCD_Cadena(pm);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment