Last active
December 24, 2015 01:19
-
-
Save jerivas/6722687 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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