Para el desarrollo he utilizado una librería de las varias que circulan por la web, después de haberlo examinado y probado.
Este proyecto fue desarrollado según requerimientos especificados, se lee el reloj cada segundo y se muestra en un display de 7 segmentos construido con diodos leds.
posee 5 pulsadores para controlar su funcionamiento como es poner la hora, cambiar a cronómetro pausar.
También posee una salida para alarma que nos avisará cuando inicia la cuenta regresiva, todo según requerimientos.
El proyecto está desarrollado en CCS 4.114 compiler y simulado en software Proteus 7.9.
En este artículo les mostraré toda la documentación para poder desarrollarlo, ustedes podrán adaptar el proyecto a sus necesidades.
El programa incluye la configuración del reloj para salida de pulsos a 1 Hz y actualización de la hora.
A continuación les muestro el diagrama de flujo del programa:
El diagrama del circuito para la simulación en proteus:
Al final podrás encontrar el enlace para descargarlo.
Para poder desarrollar una placa decircuito impreso y mostrar en un display construido con leds de 5mm les muestro un posible circuito hecho con Eagle 6.1.0.
El código del programa es el siguiente:
#include <Cronometro.h>
#include <DS1307FIN.c>
#byte PORTB = 0x06 // Identificador para el puerto B.
#byte PORTD=0X08
#byte PORTA=0X05
#byte PORTC=0X07
#BYTE OPTION_REG=0X81
#Priority int_ext, int_rb
#use fast_io(C)
int hr=0;
int min=0;
int sec=0;
int8 modo=0;
int banderaleerclk=0;
int banderaescribirhora=0;
byte CONST DISPLAY[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
int digit; // resultado de la conversion bin2bcd
int8 banderapause=0;
void tiempo(void)
{
int16 z=0;
int16 y=0;
for(z=0;z<10;z++)
{
for(y=0;y<100;y++)
{}
z++;
}
}
void muestra()
{
int8 temp1=0;
digit= bin2bcd(hr); //convierte hora a bcd
temp1=swap(digit) & 0b00000001; //filtra para leer solo la hora
temp1=DISPLAY[temp1];
bit_set(PORTA,0);
PORTD=temp1;
tiempo();
bit_clear(PORTA,0) ;
temp1=swap(digit) & 0b00001111;
temp1=DISPLAY[temp1];
bit_set(PORTA,1);
PORTD=temp1;
tiempo();
bit_clear(PORTA,1) ;
digit=bin2bcd(min); //convierte minutos a bcd
temp1=swap(digit) & 0b00001111;
temp1=DISPLAY[temp1];
bit_set(PORTA,2);
PORTD=temp1;
tiempo();
bit_clear(PORTA,2) ;
temp1=swap(digit) & 0b00001111;
temp1=DISPLAY[temp1];
bit_set(PORTA,3);
PORTD=temp1;
tiempo();
bit_clear(PORTA,3) ;
}
void muestra2()
{
int8 temp=0;
digit= bin2bcd(min); //convierte min a bcd
temp=swap(digit) & 0b00001111;
temp=DISPLAY[temp];
bit_set(PORTA,0);
PORTD=temp;
tiempo();
bit_clear(PORTA,0) ;
temp=swap(digit) & 0b00001111;
temp=DISPLAY[temp];
bit_set(PORTA,1);
PORTD=temp;
tiempo();
bit_clear(PORTA,1) ;
digit=bin2bcd(sec); //convierte sec a bcd
temp=swap(digit) & 0b00001111;
temp=DISPLAY[temp];
bit_set(PORTA,2);
PORTD=temp;
tiempo();
bit_clear(PORTA,2) ;
temp=swap(digit) & 0b00001111;
temp=DISPLAY[temp];
bit_set(PORTA,3);
PORTD=temp;
tiempo();
bit_clear(PORTA,3) ;
}
#int_rb
void pulsadores()
{
delay_ms(50);
int temp =PORTB & 0b11110000;
switch(temp)
{
case 0b11100000:
if(banderapause==1) {
if (modo==0){
if (hr<12){hr++;}
else{hr=0;}
}
else{
if (min<60){min++;}
else{min=0;}}
}
//PIN RB4
break;
case 0b11010000:
if(banderapause==1){
if (modo==0){
if (min<60){min++;}
else{min=0;}
}
else
{
if (sec<60){sec++;}
else{sec=0;}
}
}
//PIN RB5
break;
case 0b10110000:
if (modo==1)
{
modo=0;
}
else{
disable_interrupts(int_ext);
min=60;
sec=0;
//PIN RB6
if(banderapause==0)
{
output_high(pin_b1); //alarma
PORTD=0;
delay_ms(3000);
output_low(pin_b1);
enable_interrupts(int_ext);
}
modo=1;
}
break;
case 0b01110000: //inicia cronometro
if (banderapause==0){
banderapause=1;
disable_interrupts(int_ext);
}
else
{
banderapause=0;
output_high(pin_b1); //alarma
delay_ms(3000);
output_low(pin_b1);
enable_interrupts(int_ext);
}
//PIN RB7
break;
default:
break;
}
}
#int_ext
void cuentaseg()
{
switch (modo)
{
case 0: //caso reloj
banderaleerclk=1;
break;
case 1: //caso cronometro
if (sec >0)
{
sec--;
}
else if(sec==256)
{
min--;
sec=59;
}
if (min==5 && sec==0) //en 5 minutos aviso alarma
{output_high(pin_b1);}
if(min==4 && sec==56) //corta alarma
{output_low(pin_b1);}
if(min==0 && sec==5) //alarma final
{output_high(pin_b1);}
if (min==0 && sec==0)
{
//aviso de cuenta cero
{output_low(pin_b1);}
modo=0 ; //vuelve a función reloj
}
break;
}
}
#int_timer0
void tmr_error()
{
disable_interrupts(INT_TIMER0);
set_timer0(0);
if(input(pin_c1)==0)
{
banderaescribirhora=1;
}
}
void main()
{
PORTD=0;
PORTB=0;
PORTA=0x00;
set_tris_c(0b11111100);
set_tris_d(0x00);
Set_tris_a(0x00);
set_tris_b(0xf1);
// ds1307_init();
// ds1307_am(hr);
ds1307_get_time(hr,min,sec);
if((sec & 0b10000000)==0b10000000) //PARA INICIAR SOLO LA PRIMERA VEZ
{
ds1307_init();
ds1307_am(hr);
}
setup_timer_0(RTCC_INTERNAL |RTCC_DIV_256);
set_timer0(0);
ext_int_edge(L_TO_H);
enable_interrupts(int_ext);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);
delay_ms(2000);
while(1) //se repite indefinidamente
{
if(input(pin_c1)==0 && banderapause==1)
{
enable_interrupts(INT_TIMER0);
}
else
{
disable_interrupts(INT_TIMER0);
}
switch (modo)
{
case 0:
if(banderaleerclk==1)
{
banderaleerclk=0;
disable_interrupts(GLOBAL);
ds1307_get_time(hr,min,sec);
enable_interrupts(GLOBAL);
}
if (banderaescribirhora==1){
banderaescribirhora=0;
if(banderapause==1 && modo==0) //si está en reloj y interrupción deshabilitada
{
ds1307_set_date_time (10, 06, 15, 2, hr, min, sec); /// se escribe en el displositivo
ds1307_am(hr);
}
}
muestra();
break;
case 1:
muestra2();
}
}
}
Ahora una vista del modelo de nuestra placa del circuito con SketchUp y Eagle :
Las librerías para el programa puedes descargarlo a continuación:
Codigo y DSN:Aqui