Problema con la oscilación del DS1307 para un reloj digital

Hola!!
Estoy haciendo un proyecto sobre un reloj digital con el DS1307, el pic16f84A y LCD y al montar l circuito en la protoboard me aparece todo en la LCD, pero el tiempo no corre. Alguien sabe por que puede ser??
 
Muchas gracias por el esquema!!
Pero el problema es que el esquema que yo tengo, lo he simulado en proteus y funciona correctamente, pero al pasarlo a la protoboard para probarlo, el reloj y el calendario me aparece en la LCD, pero el tiempo no corre y el led de la salida del DS1307 no parpadea!
A ver si me podeis decir cual puede ser el problema.
Un saludo!!
 
Hola.
Has incluido la pila?, este chip no funciona bien sin la pila o bateria de 3.3V.
Pon el cristal lo mas cerca de los pines X1, X2 y si es posible pon a GND el cuerpo del cristal.
Acegurate que las resistencias de PullUp no esten abiertas.

Un saludo.
 
Hola!!
He echo todo lo que me has dicho pero sigue sin funcionar!
Creo que el codigo que viene en el libro del PIC16F84A está mal. Alguien sabe si es ásí?
Si alguien tiene el codigo en Hexadecimal para meterselo al PIC se lo agradecería!!

Un saludo!
 
Para que el DS1307 empiece a contar tienes que modificar un bit en concreto de uno de sus registros, ahora no recuerdo cual, pero en el datasheet viene explicado.

Un saludo
 
El lenguaje es ensamblador.asm!
El compilador que utilizo es el MPLAB, aunque en el libro del PIC16F84A ya viene el codigo en hexadecimal, pero está mal!
 
ups! yo en ensamblador no se cómo se hace para utilizar el puerto I2C.. deberías investigar sobre ello. Pero la secuencia que tienes que seguir es algo cómo:
- Start comunicación
- Envío de la dirección del DS1307, con el bit final de escritura/lectura
- Envío de la dirección del registro a escribir
- Envío del byte a escribir
- Stop comunicación

Espero que te ayude

Edito: Quizá ésto te ayude
 
Última edición:
Este es el código del Programa:

;********************************** I2C_Reloj_01.asm
Código:
************************************
;
;    ===================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;      E. Palacios, F. Remiro y L. López.        [URL="http://www.pic16f84a.com"]www.pic16f84a.com[/URL]
;       Editorial Ra-Ma.  [URL="http://www.ra-ma.es"]www.ra-ma.es[/URL]
;    ===================================================================
;
; Programa para un reloj digital en tiempo real con puesta en hora. Visualiza los datos del
; reloj en formato:    "Día  Mes  Año" (Primera línea)
;         "Día_de_la_Semana   Horas:Minutos:Segundos", (Segunda línea)
; (por ejemplo    " 7 Diciemb. 2004" (Primera línea).
;        "Martes   8:47:39" (Segunda línea).
;
; La actualización del reloj se consigue leyendo el chip DS1307, que es un reloj y
; calendario en tiempo real compatible con bus I2C.
;
; El DS1307 se configura para que genere una señal cuadrada de un 1 Hz por su pin SQW/OUT.
; Esta señal se aplica al pin de interrupción INT del PIC16F84A de manera que genera una
; interrupción cada segundo, que es cuando realiza la lectura del DS1307 y la visualiza.
;
; La "PuestaEnHora" se logra mediante dos pulsadores: "MODO" e "INCREMENTAR".
; Su modo de operación es:
;     1º    Pulsa MODO, los "Años" se ponen intermitente y se ajustan mediante el
;        pulsador INCREMENTAR.
;   2º    Pulsa MODO y pasa a ajustar los "Meses" de forma similar.
;   3º    Se va pulsando MODO secuencialmente para ajustar del modo anteriormente
;        explicado los días del mes, los días de la semana, las horas y los minutos.
;   4º    Pulsa MODO y se acabó la "PuestaEnHora", pasando a visualización normal.
;
; Cuando se ajusta una variable de tiempo, ésta debe aparecer en intermitencia.
;
; Los pulsadores MODO e INCREMENTAR se conectan a líneas del Puerto B y su
; funcionamiento se basa en interrupción por cambio en la línea del Puerto B:
;
; ZONA DE DATOS **********************************************************************

    LIST        P=16F84A
    INCLUDE        <P16F84A.INC>
    __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

    CBLOCK  0x0C
    Auxiliar                    ; Registro auxiliar.
    Intermitencia    ; Para lograr la intermitencia. Si es 0, apaga en intermitencia.
    FlagsAjuste                    ; Guarda los flags para establecer los
    ENDC                        ; ajustes de día, mes, año, hora, etc.

#DEFINE  ModoPulsador            PORTB,7        ; Los pulsadores se conectan a estos
#DEFINE  IncrementarPulsador    PORTB,6        ; pines del Puerto B.
#DEFINE  OndaCuadrada_DS1307    PORTB,0        ; La onda cuadrada al pin RBO/INT.
#DEFINE  F_AjusteAnho        FlagsAjuste,5    ; Flags para los diferentes modos de
#DEFINE  F_AjusteMes        FlagsAjuste,4    ; ajustes.
#DEFINE  F_AjusteDia        FlagsAjuste,3
#DEFINE  F_AjusteDiaSemana    FlagsAjuste,2
#DEFINE  F_AjusteHora        FlagsAjuste,1
#DEFINE  F_AjusteMinuto        FlagsAjuste,0

; ZONA DE CÓDIGOS ********************************************************************

    ORG     0
    goto    Inicio
    ORG    4
    goto    ServicioInterrupcion

Mensajes
    addwf    PCL,F
MensajeLunes
    DT "Lunes   ", 0x00
MensajeMartes
    DT "Martes  ", 0x00
MensajeMiercoles
    DT "Mierc.  ", 0x00
MensajeJueves
    DT "Jueves  ", 0x00
MensajeViernes
    DT "Viernes ", 0x00
MensajeSabado
    DT "Sabado  ", 0x00
MensajeDomingo
    DT "Domingo ", 0x00
;
MensajeEnero
    DT "  Enero ", 0x00
MensajeFebrero
    DT " Febrero", 0x00
MensajeMarzo
    DT "  Marzo ", 0x00
MensajeAbril
    DT "  Abril ", 0x00
MensajeMayo
    DT "  Mayo  ", 0x00
MensajeJunio
    DT "  Junio ", 0x00
MensajeJulio
    DT "  Julio ", 0x00
MensajeAgosto
    DT " Agosto ", 0x00
MensajeSeptiembre
    DT "Septiem.", 0x00
MensajeOctubre
    DT "Octubre ", 0x00
MensajeNoviembre
    DT "Noviemb.", 0x00
MensajeDiciembre
    DT "Diciemb.", 0x00
MensajeBlanco
    DT "        ", 0x00            ; Ocho espacios en blanco.
;
DiasSemana
    addwf    PCL,F
    nop                            ; No hay día 0 de la semana. Empiezan en
    retlw    MensajeLunes        ; el día 1 de la semana (Lunes).
    retlw    MensajeMartes        ; Día 2 de la semana.
    retlw    MensajeMiercoles    ; Día 3 de la semana.
    retlw    MensajeJueves        ; Día 4 de la semana.
    retlw    MensajeViernes        ; Día 5 de la semana.
    retlw    MensajeSabado        ; Día 6 de la semana.
    retlw    MensajeDomingo        ; Día 7 de la semana.
Meses
    addwf    PCL,F
    nop                            ; No hay mes 0x00.
    retlw    MensajeEnero        ; Empiezan en el mes 1 (Enero).
    retlw    MensajeFebrero        ; Mes 0x02
    retlw    MensajeMarzo        ; Mes 0x03
    retlw    MensajeAbril        ; Mes 0x04
    retlw    MensajeMayo            ; Mes 0x05
    retlw    MensajeJunio        ; Mes 0x06
    retlw    MensajeJulio        ; Mes 0x07
    retlw    MensajeAgosto        ; Mes 0x08
    retlw    MensajeSeptiembre    ; Mes 0x09
    nop                            ; (Como el DS1307 trabaja en BCD,
    nop                            ; estos meses se rellenan con
    nop                            ; "nop").
    nop
    nop
    nop
    retlw    MensajeOctubre        ; Mes 0x10
    retlw    MensajeNoviembre    ; Mes 0x11
    retlw    MensajeDiciembre    ; Mes 0x12
FinTablas

; Estas tablas y mensajes se sitúan al principio del programa con el propósito que no
; supere la posición 0FFh de memoria ROM de programa. De todas formas, en caso que así
; fuera se visualizaría el siguiente mensaje de error en el proceso de ensamblado:
;
    IF (FinTablas > 0xFF)
        ERROR    "Atención: La tabla ha superado el tamaño de la página de los"
        MESSG    "primeros 256 bytes de memoria ROM. NO funcionará correctamente."
    ENDIF

; Instrucciones de inicialización. ------------------------------------------------------
;
Inicio
    call    LCD_Inicializa
    bsf        STATUS,RP0            ; Acceso banco 1.
    bcf        OPTION_REG,NOT_RBPU    ; Se activan las resistencias de Pull-Up del Puerto B.
    bsf        ModoPulsador        ; Los pulsadores se configuran como entrada.
    bsf        IncrementarPulsador
    bsf        OndaCuadrada_DS1307
    bcf        OPTION_REG,INTEDG    ; Interrupción INT activa por flanco de bajada.
    bcf        STATUS,RP0            ; Acceso banco 0.
    clrf    FlagsAjuste            ; Inicializa todos los flags de la puesta en hora.
    call    DS1307_Inicializa    ; Configura la señal cuadrada que genera el 
                                ; DS1307 en su pin SQW/OUT a 1 Hz.
;
; Ahora lee el bit 7 de los segundos para saber el estado anterior del reloj antes del
; reset. Este bit es el CH (Control Halt) y permite poner en marcha (CH=0) o parar el
; reloj (CH=1). Tras la lectura pueden ocurrir dos casos:
; -    Si CH está a 0 quiere decir que anteriormente el reloj ya se ha puesto en hora alguna
;    vez y está en modo "respaldo". Es decir, ha fallado la alimentación y el DS1307 se está
;    alimentando por la batería conectada al pin "VBAT", aunque el reloj no se visualice en
;    la pantalla. Por tanto, no debe inicializarse porque se corrompería el contenido del
;    DS1307 que ya está en marcha.
; -    Si CH está a 1, quiere decir que estaba parado y es la primera vez que se pone en hora.
;
    call    DS1307_Lee            ; Lee los segundos en el DS1307 y comprueba el
    btfss    Segundo,7            ; valor del bit CH. Si es "1" salta toda la
    goto    AntesConBateria        ; inicialización de los registros y la puesta
                                ; en hora inicial.
    call    DS1307_CargaInicial    ; Realiza la carga inicial a 1 Enero de 2004.
    movlw    b'10011000'            ; Las interrupciones se deben habilitar después
    movwf    INTCON                ; de la carga inicial del DS1307.
    call    PuestaEnHoraReset    ; Puesta en hora por primera vez.
    goto    Principal
    
AntesConBateria
    movlw    b'10011000'            ; Habilita las interrupciones INT, RBI y la
    movwf    INTCON                ; general GIE.

; La sección "Principal" de mantenimiento. Pasa al modo reposo y sólo espera las
; interrupciones procedentes de la línea "SQW/OUT" del DS1307 que se producen cada
; segundo en funcionamiento normal y cada 500 ms cuando esté en la "PuestaEnHora".

Principal
    sleep
    goto    Principal

; Subrutina "ServicioInterrupcion" ------------------------------------------------------
;
; Detecta qué ha producido la interrupción y ejecuta la subrutina de atención correspondiente.

ServicioInterrupcion
    btfsc    INTCON,INTF            ; Si es una interrupción procedente de la onda
    call    Reloj                ; cuadrada del DS1307 actualiza la visualización.
    btfss    INTCON,RBIF            ; Si es una interrupción RBI lee los pulsadores.
    goto    FinInterrupcion
    btfss    ModoPulsador        ; ¿Está presionado el pulsador de "MODO"?
    call    PuestaEnHora        ; Sí, pasa a poner en hora.
    btfss    IncrementarPulsador    ; ¿Pulsado "INCREMENTAR"?
    call    Incrementar            ; Sí, pasa a incrementar el registro de tiempo
FinInterrupcion                    ; correspondiente.
    bcf        INTCON,RBIF            ; Limpia los flags de reconocimiento de la
    bcf        INTCON,INTF            ; interrupción.
    retfie

; Subrutina "Reloj" ---------------------------------------------------------------------
;
; Esta subrutina actualiza los registros Anho, Mes, Dia, DiaSemana, Hora, Minuto y 
; Segundo leyendo el DS1307 a través del bus I2C. Se ejecuta debido a la petición de
; interrupción de la señal cuadrada de 1 Hz, que procede del pin "SQW/OUT" del DS1307 y
; se ha conectado al pin RB0/INT del PIC16F84A.
;
; Esta interrupción ocurre cada segundo si está en visualización normal y cada 500 ms si
; está en puesta en hora con el objetivo de conseguir la intermitencia.
;
; Si no está en puesta en hora está en funcionamiento normal, por tanto se limita a leer
; el DS1307 y a visualizar la hora.
;
Reloj
    movf    FlagsAjuste,F        ; Si no está en puesta en hora se limita a
    btfsc    STATUS,Z            ; leer el DS1307.
    goto    Leer_DS1307

; Si está en algún modo de ajuste debe interrumpir cada 500 ms para lograr la intermitencia
; alternando la interrupción por flanco de subida o de bajada. Esto lo consigue mediante la
; operación XOR del flag INTEDG con un "1", lo cual invierte este bit cada vez que ejecuta
; la instrucción y por tanto conmuta entre flanco ascendente y descendente.

    bsf        STATUS,RP0            ; Acceso banco 1.
    movlw    b'01000000'            ; El bit INTEDG está en el lugar 6 del registro.
    xorwf    OPTION_REG,F
    bcf        STATUS,RP0            ; Acceso banco 0.

; Además complementa el registro Intermitencia para que se produzca la intermitencia
; cada 500 milisegundos cuando está en la puesta en hora.

    comf    Intermitencia,F
    goto    ActualizaReloj            ; Visualiza el reloj y sale.

Leer_DS1307

; No está en ningún modo de ajuste, sino en funcionamiento normal de reloj y pasa a leer los
; registros del reloj-calendario DS1307 a través del bus I2C. Los registros del DS1307 ya
; trabajan en formato BCD, por tanto no hay que hacer ningún tipo de conversión al leerlos.

    call    DS1307_Lee
ActualizaReloj                        ; Estas dos instrucciones se pueden
;    call    VisualizaReloj            ; obviar, ya que a continuación efectivamente 
;    return                            ; ejecuta la subrutina VisualizaReloj y
                                    ; retorna.
; Subrutina "VisualizaReloj" ------------------------------------------------------------
;
; Visualiza el reloj en formato    "Dia  Mes  Año" (Primera Línea)
;             "Día_de_la_Semana Horas:Minutos:Segundos", (Segunda Línea)
; Por ejemplo        " 7 Diciemb. 2004" (Primera Linea).
;            "Martes   8:47:39" (Segunda Línea).

; La variable ajustada debe aparecer en intermitencia. Esto se logra con ayuda de
; cualquier bit del registro Intermitencia que conmuta cada 500 ms en la subrutina Reloj.
;
VisualizaReloj
    call    LCD_Linea1                ; Se sitúa en la primera línea.
    btfss    F_AjusteDia                ; ¿Está en la puesta en hora?
    goto    EnciendeDia                ; No. Pasa a visualización normal.
    btfss    Intermitencia,0            ; Sí. Pasa a intermitencia si procede.
    goto    ApagaDia                ; Apaga en la intermitencia.
EnciendeDia
    movf    Dia,W                    ; Lo visualiza. El DS1307 ya lo da en BCD.
    call    LCD_Byte                ; Visualiza rechazando cero de las decenas.
    goto    VisualizaMes
ApagaDia
    call    LCD_DosEspaciosBlancos    ; Visualiza dos espacios en blanco.
;
VisualizaMes
    call    LCD_UnEspacioBlanco        ; Visualiza un espacio en blanco.
    btfss    F_AjusteMes                ; ¿Está en la puesta en hora?
    goto    EnciendeMes                ; No. Visualización normal.
    btfss    Intermitencia,0            ; Sí. Intermitencia si procede.
    goto    ApagaMes                ; Apaga en la intermitencia.
EnciendeMes
    movf    Mes,W                    ; Lo visualiza.
    call    EscribeMes
    goto    VisualizaAnho
ApagaMes
    movlw    MensajeBlanco
    call    LCD_Mensaje                ; Visualiza varios espacios en blanco.
;
VisualizaAnho
    btfss    F_AjusteAnho            ; ¿Está en la puesta en hora?
    goto    EnciendeAnho            ; No. Visualización normal.
    btfss    Intermitencia,0            ; Sí. Intermitencia si procede.
    goto    ApagaAnho                ; Apaga en la intermitencia.
EnciendeAnho
    call    LCD_UnEspacioBlanco        ; Visualiza un espacio en blanco.
    movlw    0x20                    ; Visualiza el "20xx", del año "dos mil ...".
    call    LCD_Byte
    movf    Anho,W
    call    LCD_ByteCompleto
    goto    VisualizaDiaSemana
ApagaAnho
    movlw    MensajeBlanco
    call    LCD_Mensaje                ; Visualiza varios espacios en blanco.
;
VisualizaDiaSemana
    call    LCD_Linea2                ; Se sitúa en la segunda línea.
    btfss    F_AjusteDiaSemana        ; ¿Está en la puesta en hora?
    goto    EnciendeDiaSemana        ; No. Visualización normal.
    btfss    Intermitencia,0            ; Sí. Intermitencia si procede.
    goto    ApagaDiaSemana            ; Apaga en la intermitencia.
EnciendeDiaSemana
    movf    DiaSemana,W                ; Lo visualiza.
    call    EscribeDiaSemana
    goto    VisualizaHoras
ApagaDiaSemana
    movlw    MensajeBlanco
    call    LCD_Mensaje                ; Visualiza varios espacios en blanco.
;
VisualizaHoras
    btfss    F_AjusteHora            ; ¿Está en la puesta en hora?
    goto    EnciendeHoras            ; No. Visualización normal.
    btfss    Intermitencia,0            ; Sí. Intermitencia si procede.
    goto    ApagaHoras                ; Apaga las horas en la intermitencia.
EnciendeHoras
    movf    Hora,W                    ; Va a visualizar las horas. 
    call    LCD_Byte                ; Visualiza rechazando cero de las decenas.
    goto    VisualizaMinutos
ApagaHoras
    call    LCD_DosEspaciosBlancos    ; Visualiza dos espacios en blanco.
;
VisualizaMinutos
    movlw    ':'                        ; Envía ":" para separar datos.
    call    LCD_Caracter    
    btfss    F_AjusteMinuto            ; ¿Está en la puesta en hora?.
    goto    EnciendeMinutos
    btfss    Intermitencia,0
    goto    ApagaMinutos
EnciendeMinutos
    movf    Minuto,W                ; Visualiza minutos.
    call    LCD_ByteCompleto
    goto    VisualizaSegundos
ApagaMinutos
    call    LCD_DosEspaciosBlancos    ; Visualiza dos espacios en blanco.
;
VisualizaSegundos
    movlw    ':'                        ; Envía ":" para separar datos.
    call    LCD_Caracter
    movf    Segundo,W                ; Visualiza segundos.
    call    LCD_ByteCompleto
    return
;
; Subrutina "EscribeDiaSemana" ----------------------------------------------------------
;
; Escribe el día de la semana en la posición actual de la pantalla, utilizando la tabla
; "DiaSemana". Supone que el Lunes es el día 1 y el Domingo el 7. 
; En el registro W se le introduce el día de la semana numérico y en la pantalla aparece el
; día de la semana en letras. Así por ejemplo si (W)=0x02 en la pantalla aparecerá "Martes".
;
; Primero comprueba que no ha superado el valor máximo para evitar problemas de saltos
; erráticos con la llamada "call DiasSemana", en caso de una lectura defectuosa de este
; dato por parte del DS1307.
;
EscribeDiaSemana
    sublw    0x07                    ; ¿Ha superado su valor máximo?
    btfsc    STATUS,C
    goto    Llamada_a_DiasSemana
    movlw    0x01                    ; Lo inicializa si ha superado su valor máximo.
    movwf    DiaSemana
Llamada_a_DiasSemana
    movf    DiaSemana,W
    call    DiasSemana
    call    LCD_Mensaje
    return

; Subrutina "EscribeMes" ----------------------------------------------------------------
;
; Escribe el mes del año en la posición actual de la pantalla, utilizando la tabla "Meses". 
;
; Primero comprueba que no ha superado el valor máximo para evitar problemas de saltos
; errático con la llamada "call Meses", en caso de una lectura defectuosa de este dato
; por parte del DS1307.
;
; El DS1307 trabaja en BCD y la tabla en binario natural. Esto es un problema que se 
; soluciona con una correcta distribución de la tabla "Meses".
;
EscribeMes
    sublw    0x12                    ; ¿Ha superado su valor máximo? (Observad que
    btfsc    STATUS,C                ; trabaja en BCD).
    goto    Llamada_a_Meses
    movlw    0x01                    ; Lo inicializa si ha superado su valor máximo.
    movwf    Mes
Llamada_a_Meses
    movf    Mes,W                    ; Retorna el resultado en el registro W.
    call    Meses
    call    LCD_Mensaje
    return

; Subrutina "PuestaEnHora" --------------------------------------------------------------
;
; Subrutina de atención a la interrupción producida por el pulsador MODO que pone en hora
; el reloj. Cada vez que pulsa se desplaza el "1" a través del registro FlagsAjuste,
; pasando a ajustar secuencialmente: años, meses, días, días de la semana, horas y minutos.
;
; Para comprender el funcionamiento de esta subrutina hay que saber que el registro
; FlagsModos contiene 5 flags que permite diferenciar cada uno de los ajustes de registros
; de tiempo:
; - "F_AjusteAnho":            bit 5 de FlagsAjuste, para ajustar los años.
; - "F_AjusteMes":             bit 4 de FlagsAjuste, para ajustar los meses.
; - "F_AjusteDia":             bit 3 de FlagsAjuste, para ajustar los días del mes.
; - "F_AjusteDiaSemana":     bit 2 de FlagsAjuste, para ajustar los días de la semana.
; - "F_AjusteHora":             bit 1 de FlagsAjuste, para ajustar las horas.
; - "F_AjusteMinuto":         bit 0 de FlagsAjuste, para ajustar los minutos.
;
; Así pues el contenido del registro FlagAjuste identifica los siguientes ajustes:
; - (FlagsAjuste)=b'00100000'. Está ajustando el registro Anho (Años).
; - (FlagsAjuste)=b'00010000'. Está ajustando el registro Mes.
; - (FlagsAjuste)=b'00001000'. Está ajustando el registro Dia.
; - (FlagsAjuste)=b'00000100'. Está ajustando el registro DiaSemana (Lunes, Martes, etc).
; - (FlagsAjuste)=b'00000010'. Está ajustando el registro Hora.
; - (FlagsAjuste)=b'00000001'. Está ajustando el registro Minuto.
; - (FlagsAjuste)=b'00000000'. Está en visualización normal del reloj en tiempo real.
;
; Pueden ocurrir tres casos:
; -    Que pulse "MODO" estando en modo de visualización normal identificado porque
;    (FlagsAjuste)=b'0000000'. En este caso debe activar el flag F_AjusteAnho, es decir,
;    carga (FlagsAjuste)=b'00100000', ya que el flag F_AjusteAnho es el bit 5 del registro
;    FlagsAjuste.
; -    Que pulse "MODO" estando ya en la puesta en hora, en cuyo caso debe pasar al
;    ajuste del siguiente registro de tiempo. Ésto lo hace mediante un desplazamiento
;    a derechas. Así por ejemplo, si antes estaba ajustando los meses, es decir: 
;    (FlagsAjuste)=b'00010000', pasará a (FlagsAjuste)=b'00001000' que se identifica
;    como ajuste de los días del mes.
; -    Que pulse "MODO" estando en el último ajuste correspondiente a los minutos,
;    (FlagsAjuste)=b'00000001', pasará a (FlagsAjuste)=b'00000000', indicando que la
;     puesta en hora ha terminado y pasa a visualización normal del reloj en tiempo real.
;
PuestaEnHora
    call    Retardo_20ms            ; Espera a que se estabilicen niveles de tensión.
    btfsc    ModoPulsador            ; Si es un rebote sale fuera.
    goto    FinPuestaEnHora
PuestaEnHoraReset                    ; Al pulsar "MODO" se apaga la variable de
    clrf    Intermitencia            ; tiempo que se va a ajustar.
    btfsc    F_AjusteMinuto            ; Si antes estaba en ajuste de minutos es que
    goto    FuncionamientoNormal    ; ha terminado. Graba datos en el DS1307 y sale.
    movf    FlagsAjuste,F            ; Si antes estaba en funcionamiento normal ahora
    btfss    STATUS,Z                 ; pasa a ajustar el año.
    goto    AjustaSiguiente            ; Sino pasa a ajustar la variable de tiempo siguiente.
    bsf        F_AjusteAnho            ; Pasa a ajustar el año.
    clrf    Segundo                    ; Inicializa contador de segundos.
    goto    FinPuestaEnHora
AjustaSiguiente                        ; Desplaza un uno a la derecha del registro
    bcf        STATUS,C                ; FlagsAjuste para ajustar secuencialmente cada
    rrf        FlagsAjuste,F            ; uno de los registros de tiempo: año, mes, día,
    goto    FinPuestaEnHora            ; día de la semana, hora y minuto.
;
; Lo siguiente se ejecuta si ya ha acabado el ajuste de la hora, es decir, pasa a
; funcionamiento normal. En este caso hay que realizar tres operaciones:
; -    Fijar la interrupción INT solo por flanco de bajada.
; -    Inicializar a cero todos los flags de ajuste contenidos en (FlagsAjuste).
; -    Escribir el DS1307 con los datos de las variables de tiempo contenidas en la
;    memoría RAM del microcontrolador.
;
FuncionamientoNormal
    bsf        STATUS,RP0                ; Acceso banco 1.
    bcf        OPTION_REG,INTEDG        ; Interrupción INT activa por flanco de bajada.
    bcf        STATUS,RP0                ; Acceso banco 0.
    clrf    FlagsAjuste                ; Inicializa los flags de ajuste.
    call    DS1307_Escribe            ; Graba los datos en el DS1307.
FinPuestaEnHora
    call    VisualizaReloj            ; Visualiza los datos del reloj digital.
    btfss    ModoPulsador            ; Ahora espera deje de pulsar.
    goto    FinPuestaEnHora
    return
    
; Subrutina "Incrementar" ---------------------------------------------------------------
;
; Subrutina de atención a la interrupción por cambio de la línea RB6 al cual se ha
; conectado el pulsador "INCREMENTAR".
;
; Incrementa según corresponda una sola de las siguientes variables: (Anho), (Mes),
; (Dia), (DiaSemana), (Hora) o (Minuto).

Incrementar
    call    Retardo_20ms            ; Espera a que se estabilice el nivel de tensión.    
    btfsc    IncrementarPulsador        ; Si es un rebote sale fuera.
    goto    FinIncrementar
    btfsc    F_AjusteAnho
    call    IncrementaAnhos
    btfsc    F_AjusteMes
    call    IncrementaMeses
    btfsc    F_AjusteDia
    call    IncrementaDias
    btfsc    F_AjusteDiaSemana
    call    IncrementaDiasSemana
    btfsc    F_AjusteHora
    call    IncrementaHoras
    btfsc    F_AjusteMinuto
    call    IncrementaMinutos
    movlw    b'11111111'
    movwf    Intermitencia            ; Visualiza siempre mientras incrementa.
    call    VisualizaReloj            ; Visualiza mientras espera que deje
    call    Retardo_200ms            ; de pulsar.
    btfss    IncrementarPulsador        ; Mientras permanezca pulsado
    goto    Incrementar                ; incrementará el dígito.
FinIncrementar
    return

; Subrutina "IncrementaMinutos" ---------------------------------------------------------
;
; Incrementa el valor de la variable Minutos. Si supera los 0x59, lo resetea.
; Este incremento se debe realizar en BCD para ello utiliza la subrutina AjusteBCD.

IncrementaMinutos
    incf    Minuto,F                ; Incrementa los minutos.
    movf    Minuto,W                ; Lo pasa a BCD.
    call    AjusteBCD
    movwf    Minuto                    ; Lo guarda.
    sublw    0x59                    ; ¿Ha superado su valor máximo?
    btfss    STATUS,C    
    clrf    Minuto                    ; Lo inicializa si ha superado su valor máximo.
    return

; Subrutina "IncrementaHoras" -----------------------------------------------------------
;
IncrementaHoras
    incf    Hora,F                    ; Incrementa las Horas.
    movf    Hora,W                    ; Ahora hace el ajuste BCD.
    call    AjusteBCD
    movwf    Hora                    ; Lo guarda.
    sublw    0x23                    ; ¿Ha superado su valor máximo?
    btfss    STATUS,C
    clrf    Hora                    ; Lo inicializa si ha superado su valor máximo.
    return

; Subrutina "IncrementaDiasSemana" ------------------------------------------------------
;
IncrementaDiasSemana
    incf    DiaSemana,F
    movf    DiaSemana,W
    sublw    .7                        ; ¿Ha superado su valor máximo?
    btfsc    STATUS,C
    goto    FinIncrementaDiasSemana
    movlw    .1                        ; Lo inicializa si ha superado su valor máximo.
    movwf    DiaSemana
FinIncrementaDiasSemana
    return

; Subrutina "IncrementaDias" ------------------------------------------------------------
;
IncrementaDias
    incf    Dia,F                    ; Incrementa.
    movf    Dia,W                    ; Ahora hace el ajuste BCD.
    call    AjusteBCD
    movwf    Dia                        ; Lo guarda.
    sublw    0x31                    ; ¿Ha superado su valor máximo?
    btfsc    STATUS,C
    goto    FinIncrementaDias
    movlw    .1                        ; Lo inicializa si ha superado su valor máximo.
    movwf    Dia
FinIncrementaDias
    return

; Subrutina "IncrementaMeses" -----------------------------------------------------------
;
IncrementaMeses
    incf    Mes,F                    ; Incrementa.
    movf    Mes,W
    call    AjusteBCD                ; Ajusta a BCD.
    movwf    Mes                        ; Lo guarda.
    sublw    0x12                    ; ¿Ha superado su valor máximo?
    btfsc    STATUS,C
    goto    FinIncrementaMeses
    movlw    .1                        ; Lo inicializa si ha superado su valor máximo.
    movwf    Mes
FinIncrementaMeses
    return

; Subrutina "IncrementaAnhos" ------------------------------------------------------------
;
; Incrementa el valor de la variable (Anhos). Cuando llega a 0x30 (BCD), lo resetea.
; Es decir, llega hasta el año 2030, que se ha considerado suficientemente alto.
; Este incremento se debe realizar en BCD para ello utiliza la subrutina AjusteBCD.
;
IncrementaAnhos
    incf    Anho,F                    ; Incrementa.
    movf    Anho,W                    ; Ahora hace el ajuste BCD.
    call    AjusteBCD
    movwf    Anho                    ; Lo guarda.
    sublw    0x30                    ; ¿Ha superado su valor máximo?.
    btfss    STATUS,C                ; Si no llega a su máximo sale.
    clrf    Anho                    ; Lo inicializa si ha superado su valor máximo.
    return

; Subrutina "AjusteBCD" -----------------------------------------------------------------
;
; Esta subrutina pasa a BCD el dato de entrada. Para ello detecta si las unidades superan
; el valor "9", en cuyo caso le suman 6 para pasarlo a BCD. Por ejemplo, si previamente
; (Minuto)=0x19, al incrementarle resulta (Minuto)=0x1A que no es un código válido BCD, si se
; le suma 6 resulta (Minuto)=0x1A+0x06=0x20 que es un código válido BCD.
;
; Entrada:    En (W) el código a convertir
; Salida:    En (W) el código convertido en BCD.
;
AjusteBCD
    movwf    Auxiliar                ; Guarda el valor del número a convertir.
    andlw    b'00001111'                ; Se queda con su parte baja.
    sublw    .9                        ; Comprueba si pasa de nueve.
    btfsc    STATUS,C
    goto    NoSuperaNueve
    movlw    .6                        ; Sí lo ha superado, por tanto le suma 6.
    addwf    Auxiliar,F
NoSuperaNueve
    movf    Auxiliar,W                ; Retorna el resultado en el registro (W).
    return

    INCLUDE <BUS_I2C.INC>            ; Subrutinas de control del bus I2C.
    INCLUDE <DS1307.INC>            ; Subrutinas de control del DS1307.
    INCLUDE <RETARDOS.INC>
    INCLUDE <LCD_4BIT.INC>
    INCLUDE <LCD_MENS.INC>
    END
    
;    ===================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;      E. Palacios, F. Remiro y L. López.        [URL="http://www.pic16f84a.com"]www.pic16f84a.com[/URL]
;       Editorial Ra-Ma.  [URL="http://www.ra-ma.es"]www.ra-ma.es[/URL]
;    ===================================================================

Esta es la libreria del DS1307:

Código:
;******************************** Librería DS1307.INC ***********************************
;
;    ===================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;      E. Palacios, F. Remiro y L. López.        [URL="http://www.pic16f84a.com"]www.pic16f84a.com[/URL]
;       Editorial Ra-Ma.  [URL="http://www.ra-ma.es"]www.ra-ma.es[/URL]
;    ===================================================================
;
; Estas subrutinas permiten realizar las tareas de manejo del reloj-calendario DS1307
; Este dispositivo transmite la información vía serie a través de un bus I2C.
;
; ZONA DE DATOS **********************************************************************

    CBLOCK
    Anho                                ; Guarda el año.
    Mes                                    ; Guarda el mes.
    Dia                                    ; Guarda el día.
    DiaSemana                            ; Guarda el día de la semana: lunes, etc.
    Hora                                ; Guarda las horas.
    Minuto                                ; Guarda los minutos.
    Segundo                                ; Guarda los segundos.
    ENDC

DS1307_DIR_ESCRITURA    EQU    0xD0        ; Dirección del DS1307.
DS1307_DIR_LECTURA        EQU    0xD1
 
; Subrutina "DS1307_Inicializa" ---------------------------------------------------------
;
; Configura la señal cuadrada que genera el DS1307 en su pin SQW/OUT a 1 Hz.

DS1307_Inicializa
    call    I2C_EnviaStart                ; Envía condición de Start.
    movlw    DS1307_DIR_ESCRITURA        ; Indica al DS1307 que el byte a escribir,
    call    I2C_EnviaByte                ; está en la posición 07h, que corresponde
    movlw    0x07                        ; al control de la señal cuadrada.
    call    I2C_EnviaByte
    movlw    b'00010000'                    ; Escribe en el registro de control para
    call    I2C_EnviaByte                ; configurar onda cuadrada del DS1307 a 1 Hz.
    call    I2C_EnviaStop                ; Termina de enviar datos.
    return

; Subrutina "DS1307_Lee" ----------------------------------------------------------------
;
; Se leen las variables de tiempo del DS1307 y se guardan en los registros correspondientes.
;
DS1307_Lee
    bcf        I2C_UltimoByteLeer
    call    I2C_EnviaStart                ; Envía condición de Start.
    movlw    DS1307_DIR_ESCRITURA        ; Indica al DS1307 que el primer byte
    call    I2C_EnviaByte                ; a leer está en la posición 00H, que corresponde
    movlw    0x00                        ; a los segundos.
    call    I2C_EnviaByte
    call    I2C_EnviaStop                ; Envía condición de Stop.
                                        ; Ahora va a leer el DS1307.
    call    I2C_EnviaStart                ; Envía condición de Start.
    movlw    DS1307_DIR_LECTURA
    call    I2C_EnviaByte
    call    I2C_LeeByte                    ; Lee los segundos.
    movwf    Segundo                        ; Lo carga en el registro correspondiente.
    call    I2C_LeeByte                    ; Lee el resto de los registros utilizando
    movwf    Minuto                        ; el mismo procedimiento.
    call    I2C_LeeByte
    movwf    Hora
    call    I2C_LeeByte
    movwf    DiaSemana
    call    I2C_LeeByte
    movwf    Dia
    call    I2C_LeeByte
    movwf    Mes
    bsf        I2C_UltimoByteLeer            ; Para terminar.
    call    I2C_LeeByte
    movwf    Anho
    call    I2C_EnviaStop                ; Acaba de leer.
    return

; Subrutina "DS1307_CargaInicial" -------------------------------------------------------
;
; Realiza una carga inicial en los registros internos del reloj-calendario DS1307 a fecha
; Lunes, 1 de Enero de 2004 a las 0:00:00.
;
DS1307_CargaInicial
    movlw    .1                            ; Inicializa todos los datos del reloj: Año, mes,
    movwf    Dia                            ; día, día de la semana, hora, minuto y segundo.
    movwf    Mes
    movwf    DiaSemana
    movlw    .4
    movwf    Anho                        ; Inicializa en el año 2004.
    clrf    Hora
    clrf    Minuto
    clrf    Segundo                        ; Después lo graba en el DS1307 para
;    call    DS1307_Escribe                ; ponerlo en marcha.
;    return
;
; Subrutina "DS1307_Escribe" ----------------------------------------------------------------
;
; Carga los datos de los registros Anho, Mes, etc., dentro del DS1307.

DS1307_Escribe
    call    I2C_EnviaStart                ; Envía condición de Start.
    movlw    DS1307_DIR_ESCRITURA        ; Indica al DS1307 que el primer byte a escribir
    call    I2C_EnviaByte                ; está en la posición 00h que corresponde
    movlw    0x00                        ; a los segundos.
    call    I2C_EnviaByte
    movf    Segundo,W                    ; Pasa los segundos de la memoria del PIC16F84A
    call    I2C_EnviaByte                ; al DS1307.
    movf    Minuto,W                    ; Y se repite el proceso para el resto.
    call    I2C_EnviaByte
    movf    Hora,W
    call    I2C_EnviaByte
    movf    DiaSemana,W
    call    I2C_EnviaByte
    movf    Dia,W
    call    I2C_EnviaByte
    movf    Mes,W
    call    I2C_EnviaByte
    movf    Anho,W
    call    I2C_EnviaByte
    call    I2C_EnviaStop                ; Termina de enviar datos.
    return

;    ===================================================================
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;      E. Palacios, F. Remiro y L. López.        [URL="http://www.pic16f84a.com"]www.pic16f84a.com[/URL]
;       Editorial Ra-Ma.  [URL="http://www.ra-ma.es"]www.ra-ma.es[/URL]
;    ===================================================================

Un saludo y Muchisimas gracias por todo!!!
 
Última edición por un moderador:
Yo tuve este problema de que el reloj no avanzaba, utilizo CCS y Proteus, en mi caso el problema era de hardware, le solde unas patillas de LEDs a las patillas del cristal y c lo puse en el mismo lugar de la protoboard en que estaba X1 y X2 para que hiciera mejor contacto, haciendo esto mi problema se resolvió
 
No, ya lo dijo anteriormente, su problema es que no está configurando el DS1307 bien.

ETM, tienes que implementar una comunicación I2C en tu firmware, para poder comunicarte con el DS1307 y asi poder configurarlo, la trama y forma de configuración está en el datashhet del DS1307, asi como su dirección de esclavo, es todo. Sobre el protocolo I2C, pues abunda la información en la red y como usarlo con el micro, también hay tutoriales sobre eso... saludos.
 
Atrás
Arriba