jueves, 30 de julio de 2015

Reloj con DS1307 y PIC 18f877

Un proyecto en el cual se desarrollará un reloj con el circuito integrado DS1307 y un microcontrolador de gama media 16f877.
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
















miércoles, 31 de diciembre de 2014

Matriz de leds con Pic16F877A


Matriz de leds con Pic 16F877A con Proteus y CCS compiler

Un proyecto que podrán simularlo en Proteus nos muestra texto en una matriz de leds de 8x 80, aunque
en la simulación solo se usó 8x60, por limites de espacio.
El codigo está desarrollado en CCS Compiler, por lo cual se hace más entendible el código.
El diagrama de flujo del programa les presento a continuación:




El diagrama electrónico Está formado por el pic 16F877A, luego los registros de desplazamiento con entrada serie y salida paralelo, El microcontrolador recibe los datos de los caracteres por interrupción del
USART  el pin RC7 del PIC que cumple la función de recepción RX, en este ejemplo se usa el virtual terminal que trae incorporado el software Proteus, para enviarle datos al microcontrolador PIC.
La información se guarda en la memoria EEPROM  interna del PIC, para el borrado se debe de accionar el interruptor SW1 (cerrarlo), luego se debe de mantener abierto para poder ingresarle otro texto.
El cristal del pic no se muestra en el diagrama ya que el Proteus no lo requiere para poder simularlo,
pero es de 20Mhz conectado entre los pines 13 OSC1   y 14 OSC2, se puede también ver el Datasheet
(hoja de datos) del PIC para más detalles de conexión.
Para poder implementarlo con una matriz de leds de 5 mm se debe de incorporar un circuito de driver
podría ser con CI como el ULN2803 o con transistores, para la simulación no era necesario implementarlo. A continuación se muestra el esquema:




El codigo para el Microcontrolador pueden descargarlo de Aquí
El archivo DSN para la simulación en Proteus Aquí


A continuación puedes ver un video.