TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: Roger_Fernandez en 03 de Agosto de 2004, 17:21:00
-
Hola!
Tengo un problema tratando de utilizar el timerkeeper de Dallas DS1302.
He tratado de seguir las indicaciones de las hojas de datos pero no he ten ido éxito. No se si el problema será de software o de hardware.
Les explico como lo he hecho. Utilizo para comandar el Timerkeeper un PIC 16F628.
La conexión física la realice de la siguiente manera:
Pin 1: Masa.
Pin 2: Cristal.
Pin 3: Cristal.
Pin 4: Masa.
Pin 5: Pin RB7 del PIC (RESET).
Pin 6: Pin RB6 del PIC (IO).
Pin 7: Pin RB5 del PIC (SCLK).
Pin 8: 5 V.
Seleccione esta forma de conexión siguiendo la recomendación de la Nota de Aplicación 82: Using the Dallas Trickle Charge Timekeeper de Dallas. En ella explica las distintas formas de conexión, dependientes del uso o no de batería de respaldo. Yo utilice la opcion 2B, que corresponde a la alimentación simple sin batería de respaldo. En mi circuito tengo una alimentación permanente sobre el timerkeeper que proviene de una batería grande. El resto del circuito tiene una alimentación que es posible desconectar, dejando solo el timerkeeper en funcionamiento.
El hardware aparentemente es muy simple y no debería tener problemas. Ahora explico el software.
La idea es tomar la fecha y la hora desde la PC, colocar estos datos en 8 bytes de la memoria RAM y mediante una rutina escribir los valores en el timerkeeper.
Luego, cuando se produzca un determinado suceso, se lee los datos del timerkeeper y se los coloca en la memoria RAM, para luego escribirlos en una memoria serial EEPROM.
Para ello disponemos de 8 bytes definidos en la memoria RAM:
;Bloque de memoria desde 70h hasta 77h
;Utilizado para almacenar la Fecha y la Hora
cblock 70h
Segundo
Minuto
Hora
Dia
Mes
DiaSemana
Ano
ProteccionEscritura
endc
Defino los puertos y los pines del PIC relacionados con el Timerkeeper
Puerto_Timer equ 06h
SCLK equ 05h
IO equ 06h
RESET equ 07h
La rutina Escribir_TimerKeeper escribe los datos en el timerkeeper de a uno, es decir direccionando cada registro individualmente.
La rutina Escribir_TimerKeeper_Burst escribe los datos en el timerkeeper en forma secuencial.
Las rutinas Leer_TimerKeeper y Leer_TimerKeeper_Burst funcionan de manera similar, pero con la lectura.
La frecuencia de clock que uso esta dentro de lo establecido. Igualmente probé con una frecuencia menor con igual resultado.
Creo haber respetado los tiempo de los flancos. El tiemerkeeper recepta los datos con el flanco ascendente del clock y los transmite con el flanco descendente.
Compare mi código con algunos que conseguí en internet y es básicamente similar.
La siguiente parte del código es cuando tomo los datos de la PC.
btfss PIR1,RCIF ;Espero que llege el byte
goto $-1
movf RCREG,W
movwf Segundo ;Cargo el byte en la memoria RAM
btfss PIR1,RCIF ;Espero que llege el byte
goto $-1
movf RCREG,W
movwf Minuto ;Cargo el byte en la memoria RAM
btfss PIR1,RCIF ;Espero que llege el byte
goto $-1
movf RCREG,W
movwf Hora ;Cargo el byte en la memoria RAM
btfss PIR1,RCIF ;Espero que llege el byte
goto $-1
movf RCREG,W
movwf Dia ;Cargo el byte en la memoria RAM
btfss PIR1,RCIF ;Espero que llege el byte
goto $-1
movf RCREG,W
movwf Mes ;Cargo el byte en la memoria RAM
btfss PIR1,RCIF ;Espero que llege el byte
goto $-1
movf RCREG,W
movwf Ano ;Cargo el byte en la memoria RAM
call Escribir_TimerKeeper_Burst
y para recuperar los datos del timerkeeper hago lo siguiente:
call Leer_TimerKeeper_Burst ;Leo datos del timerkeeper
movf Puntero_Memoria_Low,W ; Direccion de EEPROM
movwf Addressl
movf Puntero_Memoria_Hi,W
movwf Addressh
movf Dia,W ;Dato a guardar
movwf Dato
call Escribir_Byte ;Escribo dato en la EEPROM
…………………..
Cuando trato de leerlo recibo el byte 80h para todos los registros, es decir, segundos = 80h, Mes = 80h .
Las distintas notas de aplicación hacen bastante hincapié en la calidad y la capacitancia que debe tener el cristal del timerkeeper. En la casa donde lo compre, no tenían datos acerca de la capacitancia del cristal. Sin embargo, me parece que si llegara a fallar el cristal, no debería influir en la parte de comunicación, es decir en la trasferencia de datos, sino simplemente en que el reloj no ‘correría’, o no incrementaría la hora.
He probado con tres DS1302 por lo que descarto que estén defectuosos, ha no ser que halla venido toda una partida mala, cosa bastante improbable o que se estén quemando apenas los coloco, lo que también seria extraño, ya que aparentemente la conexión física es correcta.
Ahora transcribo las rutinas del timerkeeper propiamente dichas:
RegistroTK: Registro utilizado para la transferencia de datos.
ContadorBitsTK: Contador de bit para la transmisión.
;***************************************************
Escribir_TimerKeeper
bcf Puerto_Timer,SCLK
call retardo_5u
bcf Puerto_Timer,IO
bsf Puerto_Timer,RESET
call retardo_3u
movlw b"10001110" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movlw b"00000000" ; Desactivo la protecc. escritura
movwf RegistroTK
call Transmitir_Byte
movlw b"10000000" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movf Segundo,W
movwf RegistroTK
call Transmitir_Byte
movlw b"10000010" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movf Minuto,W
movwf RegistroTK
call Transmitir_Byte
movlw b"10000100" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movf Hora,W
movwf RegistroTK
call Transmitir_Byte
movlw b"10000110" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movf Dia,W
movwf RegistroTK
call Transmitir_Byte
movlw b"10001000" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movf Mes,W
movwf RegistroTK
call Transmitir_Byte
movlw b"10001100" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movf Ano,W
movwf RegistroTK
call Transmitir_Byte
movlw b"10010000" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movlw b"00000100" ; Deshabilito el Trickle Charger
movwf RegistroTK
call Transmitir_Byte
movlw b"10001110" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movlw b"10000000" ; Pongo contra escritura
movwf RegistroTK
call Transmitir_Byte
bcf Puerto_Timer,SCLK
call retardo_3u
bcf Puerto_Timer,RESET
return
;***************************************************
Leer_TimerKeeper
bcf Puerto_Timer,SCLK
call retardo_5u
bcf Puerto_Timer,IO
bsf Puerto_Timer,RESET
call retardo_3u
movlw b"10000001" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
call Recibir_Byte ; Leo el segundo
movf RegistroTK,W
movwf Segundo
movlw b"10000011" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
call Recibir_Byte ; Leo el minuto
movf RegistroTK,W
movwf Minuto
movlw b"10000101" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
call Recibir_Byte ; Leo la hora
movf RegistroTK,W
movwf Hora
movlw b"10000111" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
call Recibir_Byte ; Leo el dia
movf RegistroTK,W
movwf Dia
movlw b"10001001" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
call Recibir_Byte ; Leo el mes
movf RegistroTK,W
movwf Mes
movlw b"10001101" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
call Recibir_Byte ; Leo el año
movf RegistroTK,W
movwf Ano
bcf Puerto_Timer,IO
bcf Puerto_Timer,SCLK
call retardo_3u
bcf Puerto_Timer,RESET
return
;***************************************************
Escribir_TimerKeeper_Burst
bcf Puerto_Timer,SCLK
call retardo_5u
bcf Puerto_Timer,IO
bsf Puerto_Timer,RESET
call retardo_5u
movlw b"10001110" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movlw b"00000000" ; Desactivo la protecc escritura
movwf RegistroTK
call Transmitir_Byte
movlw b"10111110" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
movf Segundo,W
movwf RegistroTK
call Transmitir_Byte
movf Minuto,W
movwf RegistroTK
call Transmitir_Byte
movf Hora,W
movwf RegistroTK
call Transmitir_Byte
movf Dia,W
movwf RegistroTK
call Transmitir_Byte
movf Mes,W
movwf RegistroTK
call Transmitir_Byte
movf DiaSemana,W
movwf RegistroTK
call Transmitir_Byte
movf Ano,W
movwf RegistroTK
call Transmitir_Byte
movlw b"10000000"
movwf RegistroTK
call Transmitir_Byte
bcf Puerto_Timer,IO
bcf Puerto_Timer,SCLK
call retardo_3u
bcf Puerto_Timer,RESET
return
; ************************************************
Leer_TimerKeeper_Burst
bcf Puerto_Timer,SCLK
call retardo_5u
bcf Puerto_Timer,IO
bsf Puerto_Timer,RESET
call retardo_5u
movlw b"10111111" ; Transmito Byte de Control
movwf RegistroTK
call Transmitir_Byte
Banco1
bsf Puerto_Timer,IO ; I/O como entrada
Banco0
movlw 08h
movwf ContadorBytesTK
movlw Segundo
movwf FSR
LeerOtroByte
movlw 08h ; Carga la cantidad de bit a recibir
movwf ContadorBitsTK
clrf RegistroTK ; Limpia el Registro de recepcion
bcf STATUS,C ; Limpia el bit de Acarreo
rrf RegistroTK,F
bcf Puerto_Timer,SCLK
call retardo_3u ;Delay para bit de dato.
btfsc Puerto_Timer,IO ;¿El bit recibido es 0 o 1?
bsf RegistroTK,7 ; El bit recibido es 1
bsf Puerto_Timer,SCLK
call retardo_3u ;Delay para bit de dato.
decfsz ContadorBitsTK,F ;¿Se recibieron todos los datos?
goto $-9 ; Se recibe el siguiente bit
movf RegistroTK,W
movwf INDF
incf FSR,F
decfsz ContadorBytesTK,F
goto LeerOtroByte
call retardo_3u
Banco1
bcf Puerto_Timer,IO ; Pin I/O como salida
Banco0
bcf Puerto_Timer,IO
bcf Puerto_Timer,SCLK
call retardo_3u
bcf Puerto_Timer,RESET
return
;**************************************************
Transmitir_Byte
movlw 08h
movwf ContadorBitsTK
bcf Puerto_Timer,SCLK
call retardo_3u
rrf RegistroTK,F ; roto al carry bit.
btfsc STATUS,C
bsf Puerto_Timer,IO ; IO --> 1
btfss STATUS,C
bcf Puerto_Timer,IO ; IO --> 0
call retardo_3u
bsf Puerto_Timer,SCLK ; Valido el dato puesto en IO
call retardo_3u
decfsz ContadorBitsTK,F
goto $-.11
bcf Puerto_Timer,IO ; IO --> 0
return
;***************************************************
Recibir_Byte
Banco1
bsf Puerto_Timer,IO ; I/O como entrada
Banco0
movlw 08h ; Carga la cantidad de bit a recibir
movwf ContadorBitsTK
clrf RegistroTK ; Limpia el Registro de recepcion
bcf STATUS,C ; Limpia el bit de Acarreo
rrf RegistroTK,F
bcf Puerto_Timer,SCLK
call retardo_3u ; Delay para bit de dato.
btfsc Puerto_Timer,IO ; ¿El bit recibido es 0 o 1?
bsf RegistroTK,7 ; El bit recibido es 1
bsf Puerto_Timer,SCLK
call retardo_3u ; Delay para bit de dato.
decfsz ContadorBitsTK,F ; ¿Se recibieron todos los datos?
goto $-9 ; Se recibe el siguiente bit
Banco1
bcf Puerto_Timer,IO ; I/O como salida
Banco0
return
;************************************************
Si alguien tiene experiecia con ese integrado le agradezco desde ya cualquier ayuda.
Saludos.
Roger. -- Carlos Paz. Cordoba. Argentina