Reloj digital con pic 16F877A ?

Buenas, tengo un problema con un reloj digital que estoy diseñando, lo estoy diseñando en C.
Es un reloj que da minutos y horas, junto con AM y PM.
Tiene que usar un único registro para Horas y otro para Minutos.

El problema me parece que lo tengo cuando hago la conversión de Dec(binario) to BCD, para mostrarlo por los puertos.

Anexo mi código base, para ver si alguien puede ayudarme.

Código:
#include <16F877a.h>    ///   libreria para el manejo del pic16f877a
#use delay(clock=4000000)      ///   declara  la frecuencia del cristal
#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT

#byte porta = 5  // declaramos los puertos a usar
#byte portb = 6
#byte portc = 7
#byte portd = 8
#byte porte = 9
#byte tmr0 = 1
#byte status = 3
#byte option_reg = 81 
#byte intcon = 0x000B



char Dec2Bcd (char decimalByte)
{
  return (((decimalByte / 10) << 4) | (decimalByte % 10));
}


char minutos=0,horas=1,am=1,pm=0, minutosBCD, unidades, decenas=1, horasBCD, aux1=0;

//Función para transformar de binario(decimal) a 7 segmentos:
char Bin2_7seg(char digit){
 switch (digit){
   case 0: return 0x3F;  //0x3F es el código 7-segmentos del 0.
   case 1: return 0x06;  //0x06 es el código 7-segmentos del 1.
   case 2: return 0x5B;
   case 3: return 0x4F;
   case 4: return 0x66;
   case 5: return 0x6D;
   case 6: return 0x7D;
   case 7: return 0x07;
   case 8: return 0x7F;
   case 9: return 0x67;
 }
}




void SUMAR(){
if(minutos<59){
minutos++;}
if(minutos>59)
{minutos==0;
 horas++;
}
if(horas>12)
{horas==0;
if(am=1){
am==0;
pm==1;
if(pm=1)
{am==1;
pm==0;}
}
}
}



void t5ms()
{
tmr0==(236);

while(tmr0<254)
{tmr0++;
}
}



void MinutosU()
{
 //Transformar los minutos para su presentación: Unidad
  minutosBCD=Dec2Bcd(minutos);          //Transforma de binario a BCD.
  unidades=0b1111&minutosBCD;           //Sacar las unidades.
  decenas=0b11110000&minutosBCD;        //Sacar las decenas.
  decenas=decenas>>4;                   //Desplazar 4 bits a la derecha.
  PORTD=Bin2_7seg(unidades);            //Unidades al puerto D.
}

void MinutosD()\
{
 //Transformar los minutos para su presentación:
  minutosBCD=Dec2Bcd(minutos);          //Transforma de binario a BCD.
  unidades=0b1111&minutosBCD;           //Sacar las unidades.
  decenas=0b11110000&minutosBCD;        //Sacar las decenas.
  decenas=decenas>>4;                   //Desplazar 4 bits a la derecha.
  PORTD=Bin2_7seg(decenas);            //Decenas al puerto D.
}




void HoraU()
{
 //Transformar las horas para su presentación:
  horasBCD=Dec2Bcd(horas);              //Transforma de binario a BCD.
  unidades=0b1111&horasBCD;             //Sacar las unidades.
  decenas=0b11110000&horasBCD;          //Sacar las decenas.
  decenas=decenas>>4;                   //Desplazar 4 bits a la derecha.
  PORTD=Bin2_7seg(unidades);            //Unidades al puerto D.
}

Void HoraD()
{
 //Transformar las horas para su presentación:
  horasBCD=Dec2Bcd(horas);              //Transforma de binario a BCD.
  unidades=0b1111&horasBCD;             //Sacar las unidades.
  decenas=0b11110000&horasBCD;          //Sacar las decenas.
  decenas=decenas>>4;                   //Desplazar 4 bits a la derecha.
  if (decenas==1)
   PORTD=Bin2_7seg(decenas);            //Decenas al puerto D.
  if (decenas==2)
   PORTD=0x3B;                          //Formar el número "2".
  if (decenas==0) PORTA=0;              //Apagar las decenas cuando valgan cero.
}



void TIME1()
{
while(aux1<49)
{
aux1++;
}
aux1==0;
}



void PRE(){



}








void BARRIDO()
{
PIN_E0==(1);  // Seleccionamos el display // Minutos > Unidad
PIN_E1==(0); // Minutos > Decena 
PIN_E2==(0); // Hora > Unidad
PIN_A3==(0); // Hora > Decena
MinutosU();
t5ms();
PIN_E0==(0);  // Seleccionamos el display // Minutos > Unidad
PIN_E1==(1); // Minutos > Decena 
PIN_E2==(0); // Hora > Unidad
PIN_A3==(0); // Hora > Decena
MinutosD();
t5ms();
PIN_E0==(0);  // Seleccionamos el display // Minutos > Unidad
PIN_E1==(0); // Minutos > Decena 
PIN_E2==(1); // Hora > Unidad
PIN_A3==(0); // Hora > Decena
HoraU();
t5ms();
PIN_E0==(0);  // Seleccionamos el display // Minutos > Unidad
PIN_E1==(0); // Minutos > Decena 
PIN_E2==(1); // Hora > Unidad
PIN_A3==(0); // Hora > Decena
HoraD();
t5ms();
}










void main ()

{
// Los transistores estan en el puerto E y el que falta en RA3

setup_adc_ports(NO_ANALOGS);
set_tris_a(0b00100011); // RA0: Inicio o parado del reloj. RA1: Reseteo. Alarma. RA5: 2 Puntos a 1Hz
set_tris_b(0b00000001); // RB0 boton para configurar y activar alarma
set_tris_c(0b11111111); // teclado matricial
set_tris_d(0b00000000); // horas/minutos
set_tris_e(0b000);
OPTION_REG=0b01010111;      //Pull ups habilitados.Timer0 como temporizador. //Prescaler asignado al Timer0. Prescaler 1:256.
INTCON=0b10010000;   






while(true){
PIN_A5==(1); 
TIME1();
PIN_A5==(0);
if(bit_test(porta,0))
{
SUMAR();
}
if(bit_test(porta,1))
{
minutos==0;
horas==1;
unidades==0;
decenas==1;
}
}
}
Espero puedan ayudarme :)
 
Última edición por un moderador:
Tienes muchos errores de asignación en tu programa.
Por ejemplo aquí:
if(minutos>59)
{minutos==0;
horas++;
}
Debería ser...
if(minutos>59)
{minutos=0;
horas++;
}
Y así, en varias sentencias If tienes el mismo problema.
Cuando compares/preguntes usa == y cuando asignes solo usa =

Aquí por ejemplo, lo haces al revés:
if(am=1){
am==0;
pm==1;
Debería ser...
if(am==1){
am=0;
pm=1;

En otra parte de tu código (BARRIDO) tienes este problema:
PIN_E0==(1)
Tienes que hacerlo de esta forma...
output_high(PIN_E0);
Lo mismo para los pines que quieras poner a nivel bajo...
output_low(PIN_XX);

Corrige todo eso primero y ve como funciona tu programa con esas correcciones.

Saludos.
 
Código:
#include <16F877a.h>    ///   libreria para el manejo del pic16f877a
#use delay(clock=4000000)      ///   declara  la frecuencia del cristal
#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT,NOPROTECT
#include <KBD.C>
#define use_portd_kbd TRUE


#byte port_a = 0x05  // declaramos los puertos a usar
#byte port_b = 0x06
#byte port_c = 0x07
#byte port_d = 0x08
#byte port_e = 0x09


char minutos=0,horas=12,am=1,pm=0, unidades, decenas=0, tecla, tecla1, tecla2, tecla5, tecla4, tecla3;
int32 aux1;


#int_TIMER0
void int_tmr0(void)  {
aux1++;
if(aux1>10){
Output_toggle(PIN_A5);
aux1=0;
minutos++;
if(minutos>59)
{minutos = 0;
horas++;
if(horas>12){
horas = 1;

}

}

if(minutos==59)
{if(horas==11)
{Output_toggle(PIN_A2);
set_timer0(0x12);

}

}
}
}


int bin2bcd(char valor){  // Funcion que convierte de Binario a BCD 

  decenas=0; 

  if (valor>=10){ 
    do{ 
      valor-=10; 
      decenas++; 
    }while (valor>=10); 
  } 
  unidades=valor; 
  return;
} 


//Función para transformar de binario(decimal) a 7 segmentos:
int Bin2_7seg(char digit){
 switch (digit){
   case 0: return 0x3F;  //0x3F es el código 7-segmentos del 0.
   case 1: return 0x06;  //0x06 es el código 7-segmentos del 1.
   case 2: return 0x5B;
   case 3: return 0x4F;
   case 4: return 0x66;
   case 5: return 0x6D;
   case 6: return 0x7D;
   case 7: return 0x07;
   case 8: return 0x7F;
   case 9: return 0x67;
 }
}


Void Barrido(){
bin2Bcd(minutos);          //Transforma de binario a BCD.
Output_Low(PIN_E0);  // Seleccionamos el display // Minutos > Unidad
Output_High(PIN_E1); // Minutos > Decena 
Output_High(PIN_E2); // Hora > Unidad
Output_High(PIN_A3); // Hora > Decena
PORT_B=Bin2_7seg(unidades); //Unidades al puerto D.
delay_ms(5);
Output_High(PIN_E0);  // Seleccionamos el display // Minutos > Decena
Output_Low(PIN_E1); // Minutos > Decena 
Output_High(PIN_E2); // Hora > Unidad
Output_High(PIN_A3); // Hora > Decena
PORT_B=Bin2_7seg(decenas); // Decenas al puerto D.
delay_ms(5); 


bin2Bcd(horas); // Transforma de binario a BCD.
Output_High(PIN_E0);  // Seleccionamos el display // Horas > Unidad
Output_High(PIN_E1); // Minutos > Decena 
Output_Low(PIN_E2); // Hora > Unidad
Output_High(PIN_A3); // Hora > Decena
PORT_B=Bin2_7seg(unidades); //Unidades al puerto D.
delay_ms(5);
Output_High(PIN_E0);  // Seleccionamos el display // Minutos > Decena
Output_High(PIN_E1); // Minutos > Decena 
Output_High(PIN_E2); // Hora > Unidad
Output_Low(PIN_A3); // Hora > Decena
PORT_B=Bin2_7seg(decenas); // Decenas al puerto D.
delay_ms(5); 


}


void main (void)

{
// Los transistores estan en el puerto E y el que falta en RA3

setup_adc_ports(NO_ANALOGS);
set_tris_a(0b000000); // RA0: Inicio o parado del reloj. RA1: Reseteo. Alarma. RA5: 2 Puntos a 1Hz RA2= am/pm
set_tris_b(0b00000000); // 
set_tris_c(0b00000000); // teclado matricial
set_tris_d(0b11110000); // horas/minutos
set_tris_e(0b000);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
disable_interrupts(INT_TIMER0);
disable_interrupts(GLOBAL);

port_a=0x00;
port_b=0x00;
port_c=0x00;
port_d=0x00;
port_e=0x00;

set_TIMER0(12);








while(true){


Barrido();

do
         {
            tecla=kbd_getc();
         }while(tecla==0);
          
    if(tecla!=0)                    // Si hubo alguna tecla pulsada
    {
        delay_ms(5);      // Delay antirrebote
        tecla2 = kbd_getc();   // Escanear otra vez
        if( tecla==tecla2)        // Si Ambas teclas leídas son iguales 
        tecla3=tecla2;            // guarda la tecla oprimida
        
    }
        
        if(tecla3=1)
        {tecla= kbd_getc();       
         if(tecla)                    // Si hubo alguna tecla pulsada
        {
           delay_ms(5);      // Delay antirrebote
           tecla2 = kbd_getc();   // Escanear otra vez
           if( tecla==tecla2)        // Si Ambas teclas leídas son iguales 
            tecla4=tecla2;            // guarda la tecla oprimida
        }
        if(tecla4=2)
        {
       enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
        }
        }
    }     
}
muchas gracias por responder, ya hace unos días había leído mas del tema de programar en C y había corregido esos errores.

Ya he logrado que tenga sus segundero (Dos leds en RA5), que cuente minutos y horas perfectamente, que tenga AM, PM (Led en RA2) etc. Ahora necesito agregarle un teclado matricial, pero a la hora de usar el teclado (por el puertoD) no me deja. no se porque, no se si me haga falta configurar algo. cuando uso la expresión

"tecla=kbd_getc();" los displays se me vuelven locos y no muestran la hora ni nada

y cuando uso "tecla=kbd_getc;" los displays si muestran la hora normal y cuentan.

Por otro lado no se que mas deba agregar para que funcione el teclado.

Anexo imagen de como va el circuito

http://imageshack.com/scaled/800x600/856/90n2.png

PD: alguien podría decirme como configurar mi "Barrido" en conjunto con transistores para que funcione perfectamente con los displays y tenerlos multiplexados? no logro hacerlos funcionar bien.


EDIT: Ya he logrado que los displays funcionen y el teclado en el puerto D, ahora lo que no hace es tomarme los numeros.
 
Última edición:
Atrás
Arriba