I need help whit develop of a RTC whit a PIC 16F873A. The code dont work well, only display the initial values but the RTC is run!! The hours and seconds I display on a seven segment display. I use MPLAB 7.60 and my oscillator is 4 Mhz.
The code is following:
; Clock Calendar display in SEVEN SEGMENT
; Fecha 1° de Noviembre de 2.007
; 1° correción 08/02/2008
; 2° correcion 04/04/2008
; por Ing. José Enrique Benítez M.-
#include <C:\ARCHIVOS DE PROGRAMA\Microchip\MPASM Suite\P16F873A.inc>
list p = PIC16F873A
__config H'3F79' ; this config gives us LVP and enables /MCLR
errorlevel -302 ; do not print message for operands that are not in bank 0
RESET org 0x02
goto START
org 0x30
;define Bus Clock Line y Bus Data Line
;Serial Clock Line SCL = portc,3
;Serial Data Line SDA = portc,4
w equ H'0000' ; Ante cualquier instruccion, el resultado se guarda en W
same equ H'0001' ; el resultado de cualquier instrucción guardo en el mismo registro
CBLOCK 0X20
DIG1 ; REGISTRO DE CENTENAS
DIG2 ; REGISTRO DE DECENAS
DIG3 ; REGISTRO DE UNIDADES
DIGTEMP
digi
ONE
YRS
MON
DOW
DAYS
HRS
MINS
SECS
CNT1
CNT2
contatore_1
contatore_2
contatore_3
ENDC
;Direcciones de lectura y escritura del RTC
DS1307_Write equ 0xD0
DS1307_Read equ 0XD1
DIGBYTE MACRO ONE
local cent
local dece
local unit
local positivo
clrf DIG1
clrf DIG2
clrf DIG3
positivo
movf ONE,w
movwf DIGTEMP
movlw 0x64
cent incf DIG1,same
subwf DIGTEMP,same
btfsc STATUS,C
goto cent
decf DIG1,same
addwf DIGTEMP,same
dece movlw 0x0A
incf DIG2,same
subwf DIGTEMP,same
btfsc STATUS,C
goto dece
decf DIG2,same
addwf DIGTEMP,same
unit movf DIGTEMP,w
movwf DIG3
ENDM
BANK0 MACRO
bcf STATUS, RP0
bcf STATUS, RP1
ENDM
BANK1 MACRO
bsf STATUS, RP0
bcf STATUS, RP1
ENDM
S_START MACRO
bcf PIR1,SSPIF
BANK1
bsf SSPCON2,SEN ; Activa secuencia de Inicio
BANK0
btfss PIR1,SSPIF ; Ha terminado?
goto $-2 ; no, esperar
ENDM
S_STOP MACRO ; assumes SCL is high on entry
bcf PIR1,SSPIF
BANK1
bsf SSPCON2,PEN ; Activa secuencia de parada
btfsc SSPCON2,PEN ; has stop bit been sent?
goto $-2
BANK0
btfss PIR1,SSPIF
goto $-2
ENDM
;---------------------------------------------------------
;RETARDOS
DELAY_OFF movwf CNT1 ; CNT1 se carga antes con el decimal 24
clrf contatore_2
ton decfsz contatore_2,same
goto ton
decfsz CNT1,same
goto ton
retlw 0x0
DELAY_ON
movlw 0x0F
movwf CNT2
toff clrf TMR0 ; reseteo TMR0
decfsz CNT2,f
goto toff
retlw 0x0
;-----------------------------------------
; -- RTC routines --
;-----------------------------------------
; Lee un byte procedente del RTC seleccionado y lo mete en los registros correspondientes
; de hora, minuto y segundo, etc.
RTC_read
S_START
movlw DS1307_Write ; slave address + write
call write_RTC
movlw 0X00 ; set word address to seconds register
call write_RTC
S_STOP ; Envía condición de STOP
S_START ; Ahora va a leer el DS1307
movlw DS1307_Read ; slave address + read
call write_RTC
; -- Aqui hay un cambio de señales de WRITE a READ!! --
call read_RTC ; read the seconds data
movwf SECS ; save it
call read_RTC ; and so on
movwf MINS
call read_RTC
movwf HRS
call read_RTC
movwf DOW
call read_RTC
movwf DAYS
call read_RTC
movwf MON
call read_RTC
movwf YRS
bsf SSPCON2,ACKDT ; Genera un NACK el MASTER
bsf SSPCON2,ACKEN ; despues de recibir de last byte
btfsc SSPCON2,ACKEN ; has ACKDT bit been sent yet?
goto $-2
S_STOP
return
;*******Grabación de datos en el RTC********
RTC_write
S_START
movlw DS1307_Write ; slave address + write
call write_RTC
movlw 0X00 ; set word address to seconds register
call write_RTC
movf SECS, W
call write_RTC
movf MINS, W
call write_RTC
movf HRS, W
call write_RTC
movf DOW, W
call write_RTC
movf DAYS, W
call write_RTC
movf MON, W
call write_RTC
movf YRS, W
call write_RTC
S_STOP
return
;---- Read RTC into W ----Recibir del SLAVE
;Lee un byte procedente del RTC y lo mete en working
;a cotinuacion no genera un ACK, en cambio envía un bit de STOP
read_RTC
bcf PIR1,SSPIF ; Restaura Flag MSSP
BANK1
bsf SSPCON2,RCEN ; Activa MSSP a modo receptor
BANK0
btfss PIR1,SSPIF ; ¿Byte recibido?
goto $-2 ; no, esperar, loop back to test
bcf PIR1, SSPIF ; ¡SI, restaura Flag MSSP
BANK1
bcf SSPCON2,ACKDT ; pone bit ACK a 1, no envía ACK
bsf SSPCON2,ACKEN ; Sent ACKDT bit
btfsc SSPCON2,ACKEN ; has ACKDT bit been sent yet?
goto $-2
btfsc SSPCON2,RCEN ; test read bit state
goto $-2 ; module busy, so wait
movf SSPBUF,W ; Sí! Lee el byte recibido y lo coloca en working
return
; --- Write the byte in W to RTC ---
; ---- Escribir ó enviar un dato al SLAVE ----
; Escribe un byte que se encuentra en working vía I2C al RTC ----
write_RTC
SENT bcf PIR1, SSPIF ; Restaura Flag MSSP
movwf SSPBUF ; Llevar byte a buffer de salida
btfss PIR1, SSPIF ; has SSP completed sending data to SLAVE?
goto $-2 ; no, esperar
btfsc SSPCON2,ACKSTAT ; ¿Recibido, ACK?
goto $-2 ; no, try again
return ; yes, return to calling routine
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++
;--------- start ------------------------------------
;-------------------------------------------------------
START
BANK0
clrf CNT1
clrf CNT2
clrf contatore_1
clrf contatore_2
clrf PORTA ; initialize PORTA
clrf PORTB ; initialize PORTB
clrf PORTC ; initialize PORTC
BANK1
movlw 0x06
movwf ADCON1 ; Puerta A -- E/S DIgital
movlw 0x00 ; B´00000000´
movwf TRISB ; set pinsB for output
movwf TRISA ; set pinsA for output
bsf TRISC,3 ; I2C SCL pin is input
bsf TRISC,4
movlw 0x80 ; Velocidad standart con
movwf SSPSTAT ; niveles I2C
movlw 0x09 ; Velocidad del BUS I2C
movwf SSPADD ; 100 Khz
bsf PORTC,3
bsf PORTC,4
;Configuración del módulo MSSP en modo master I2C
movlw 0x28 ; Módulo MSSP en ON
movwf SSPCON
;Subrutina "DS1307_Inicializa" ;------------------------------------------------
;Configura la señal cuadrada que genera el DS1307 en su pin SQW/OUT a 1 Hz.
S_START ; Envía condición de start
movlw DS1307_Write ; Indica al DS1307 que el byte a escribir,
call write_RTC ; está en la posición 07h, que corresponde
movlw 0x07 ; al control de la señal cuadrada.
call write_RTC
movlw b'00010000' ; Escribe en el registro de control para
call write_RTC ; configurar onda cuadrada del DS1307 a 1 Hz.
movlw 0x00 ; Indica el registro de control CERO para
call write_RTC ; configurar CH del DS1307 a 0.
movlw b'00000000' ; configurar BIT 7 a 0
call write_RTC ; Clock Halt
movlw 0x02 ; Indica el registro de control DOS para
call write_RTC ; configurar Modo 12 ó 24 hrs.
movlw b'00000000' ; configurar BIT 6 a 0
call write_RTC ; Modo 24-horas
S_STOP ; Termina de enviar datos.
;----------------------------------------*******************************
;Subrutina "DS1307_Carga_Inicial" ;---------SET CLOCK--------------------
;Realiza una carga inicial en los registros internos del reloj-calendario
;DS1307 a fecha Lunes, 27 de Abril de 2008 a las 16:55:00 horas
;---------------------------------------------
;-- write to the RTC with user-entered data --
;---------------------------------------------
movlw 0x1B ; inicializa todos los datos del reloj: Año, mes,
movwf DAYS ; día, día de la semana, hora, minuto y segundo.
movlw 0x04
movwf MON
movwf DOW
movlw 0x08
movwf YRS ; Inicializa en el año 2008
movlw 0x10 ; 10 = 16
movwf HRS
movlw 0x37 ; 37 = 55
movwf MINS
clrf SECS ; Después lo graba en el DS1307 para ponerlo en marcha
call RTC_write
; Subrutina "DS1307_Lee" ;------------------------------------------------------
; Se leen las variables de tiempo del DS1307 y se guardan en los registros correspondientes
DISPLAY nop
call RTC_read ; leer clock - calendar
;---------------------------------------------
;-- display RTC data --
;---------------------------------------------
movlw high TABLA
MOVWF PCLATH
MAIN MOVF SECS,W ; Traigo el byte en formato BCD de los MINUTOS
MOVWF digi
DIGBYTE digi ; LLamada a MACRO P/ Extraccion de DIGITOS
MOVLW 0XFF ; CARGAR W con 1s
MOVWF PORTA ; para inhibir transistores
CALL DELAY_ON
MOVF DIG3,W ; Traer de macro las unidades
CALL TABLA
MOVWF PORTB ; ENVIAR DATO A SEGMENTO
BCF PORTA,0 ; Se excita la base del transistor 1
MOVLW 0X09 ; CARGO W PARA RETARDO DE 5ms *** 1A=26
CALL DELAY_OFF
MOVLW 0XFF
MOVWF PORTA ; Apago display
CALL DELAY_ON
MOVF DIG2,W
CALL TABLA
MOVWF PORTB
BCF PORTA,1 ; Se prende el transistor 2
MOVLW 0X09 ; 1A = 26 ** 09 = 24
CALL DELAY_OFF
MOVF MINS,W ; Traigo la información de HORA
MOVWF digi
DIGBYTE digi ; LLamada a MACRO P/ Extraccion de DIGITOS
MOVLW 0XFF ; CARGAR W con 1s
MOVWF PORTA ; para inhibir transistores
CALL DELAY_ON
MOVF DIG3,W ; Traer de macro las unidades
CALL TABLA
MOVWF PORTB ; ENVIAR DATO A SEGMENTO
BCF PORTA,2 ; Se excita la base del transistor 3
MOVLW 0X09 ; CARGO W PARA RETARDO DE 5ms *** 1A=26
CALL DELAY_OFF
MOVLW 0XFF
MOVWF PORTA ; Apago display
CALL DELAY_ON
MOVF DIG2,W
CALL TABLA
MOVWF PORTB
BCF PORTA,3 ; Se prende el transistor BC560 número 4
MOVLW 0X09 ; 1A = 26 ** 09 = 24
CALL DELAY_OFF
CALL DELAY_ON
GOTO DISPLAY
TABLA ADDWF PCL,1 ; .gfedcba con ULN
RETLW 0XBF ;B01000000 == 0
RETLW 0X86 ;B01111001 == 1
RETLW 0XDB ;B00100100 == 2
RETLW 0XCF ;B00110000 == 3
RETLW 0XE6 ;B00011001 == 4
RETLW 0XED ;B00010010 == 5
RETLW 0XFD ;B00000010 == 6
RETLW 0X87 ;B01111000 == 7
RETLW 0XFF ;B00000000 == 0
RETLW 0XEF ;B00010000 == 9
end
The code is following:
; Clock Calendar display in SEVEN SEGMENT
; Fecha 1° de Noviembre de 2.007
; 1° correción 08/02/2008
; 2° correcion 04/04/2008
; por Ing. José Enrique Benítez M.-
#include <C:\ARCHIVOS DE PROGRAMA\Microchip\MPASM Suite\P16F873A.inc>
list p = PIC16F873A
__config H'3F79' ; this config gives us LVP and enables /MCLR
errorlevel -302 ; do not print message for operands that are not in bank 0
RESET org 0x02
goto START
org 0x30
;define Bus Clock Line y Bus Data Line
;Serial Clock Line SCL = portc,3
;Serial Data Line SDA = portc,4
w equ H'0000' ; Ante cualquier instruccion, el resultado se guarda en W
same equ H'0001' ; el resultado de cualquier instrucción guardo en el mismo registro
CBLOCK 0X20
DIG1 ; REGISTRO DE CENTENAS
DIG2 ; REGISTRO DE DECENAS
DIG3 ; REGISTRO DE UNIDADES
DIGTEMP
digi
ONE
YRS
MON
DOW
DAYS
HRS
MINS
SECS
CNT1
CNT2
contatore_1
contatore_2
contatore_3
ENDC
;Direcciones de lectura y escritura del RTC
DS1307_Write equ 0xD0
DS1307_Read equ 0XD1
DIGBYTE MACRO ONE
local cent
local dece
local unit
local positivo
clrf DIG1
clrf DIG2
clrf DIG3
positivo
movf ONE,w
movwf DIGTEMP
movlw 0x64
cent incf DIG1,same
subwf DIGTEMP,same
btfsc STATUS,C
goto cent
decf DIG1,same
addwf DIGTEMP,same
dece movlw 0x0A
incf DIG2,same
subwf DIGTEMP,same
btfsc STATUS,C
goto dece
decf DIG2,same
addwf DIGTEMP,same
unit movf DIGTEMP,w
movwf DIG3
ENDM
BANK0 MACRO
bcf STATUS, RP0
bcf STATUS, RP1
ENDM
BANK1 MACRO
bsf STATUS, RP0
bcf STATUS, RP1
ENDM
S_START MACRO
bcf PIR1,SSPIF
BANK1
bsf SSPCON2,SEN ; Activa secuencia de Inicio
BANK0
btfss PIR1,SSPIF ; Ha terminado?
goto $-2 ; no, esperar
ENDM
S_STOP MACRO ; assumes SCL is high on entry
bcf PIR1,SSPIF
BANK1
bsf SSPCON2,PEN ; Activa secuencia de parada
btfsc SSPCON2,PEN ; has stop bit been sent?
goto $-2
BANK0
btfss PIR1,SSPIF
goto $-2
ENDM
;---------------------------------------------------------
;RETARDOS
DELAY_OFF movwf CNT1 ; CNT1 se carga antes con el decimal 24
clrf contatore_2
ton decfsz contatore_2,same
goto ton
decfsz CNT1,same
goto ton
retlw 0x0
DELAY_ON
movlw 0x0F
movwf CNT2
toff clrf TMR0 ; reseteo TMR0
decfsz CNT2,f
goto toff
retlw 0x0
;-----------------------------------------
; -- RTC routines --
;-----------------------------------------
; Lee un byte procedente del RTC seleccionado y lo mete en los registros correspondientes
; de hora, minuto y segundo, etc.
RTC_read
S_START
movlw DS1307_Write ; slave address + write
call write_RTC
movlw 0X00 ; set word address to seconds register
call write_RTC
S_STOP ; Envía condición de STOP
S_START ; Ahora va a leer el DS1307
movlw DS1307_Read ; slave address + read
call write_RTC
; -- Aqui hay un cambio de señales de WRITE a READ!! --
call read_RTC ; read the seconds data
movwf SECS ; save it
call read_RTC ; and so on
movwf MINS
call read_RTC
movwf HRS
call read_RTC
movwf DOW
call read_RTC
movwf DAYS
call read_RTC
movwf MON
call read_RTC
movwf YRS
bsf SSPCON2,ACKDT ; Genera un NACK el MASTER
bsf SSPCON2,ACKEN ; despues de recibir de last byte
btfsc SSPCON2,ACKEN ; has ACKDT bit been sent yet?
goto $-2
S_STOP
return
;*******Grabación de datos en el RTC********
RTC_write
S_START
movlw DS1307_Write ; slave address + write
call write_RTC
movlw 0X00 ; set word address to seconds register
call write_RTC
movf SECS, W
call write_RTC
movf MINS, W
call write_RTC
movf HRS, W
call write_RTC
movf DOW, W
call write_RTC
movf DAYS, W
call write_RTC
movf MON, W
call write_RTC
movf YRS, W
call write_RTC
S_STOP
return
;---- Read RTC into W ----Recibir del SLAVE
;Lee un byte procedente del RTC y lo mete en working
;a cotinuacion no genera un ACK, en cambio envía un bit de STOP
read_RTC
bcf PIR1,SSPIF ; Restaura Flag MSSP
BANK1
bsf SSPCON2,RCEN ; Activa MSSP a modo receptor
BANK0
btfss PIR1,SSPIF ; ¿Byte recibido?
goto $-2 ; no, esperar, loop back to test
bcf PIR1, SSPIF ; ¡SI, restaura Flag MSSP
BANK1
bcf SSPCON2,ACKDT ; pone bit ACK a 1, no envía ACK
bsf SSPCON2,ACKEN ; Sent ACKDT bit
btfsc SSPCON2,ACKEN ; has ACKDT bit been sent yet?
goto $-2
btfsc SSPCON2,RCEN ; test read bit state
goto $-2 ; module busy, so wait
movf SSPBUF,W ; Sí! Lee el byte recibido y lo coloca en working
return
; --- Write the byte in W to RTC ---
; ---- Escribir ó enviar un dato al SLAVE ----
; Escribe un byte que se encuentra en working vía I2C al RTC ----
write_RTC
SENT bcf PIR1, SSPIF ; Restaura Flag MSSP
movwf SSPBUF ; Llevar byte a buffer de salida
btfss PIR1, SSPIF ; has SSP completed sending data to SLAVE?
goto $-2 ; no, esperar
btfsc SSPCON2,ACKSTAT ; ¿Recibido, ACK?
goto $-2 ; no, try again
return ; yes, return to calling routine
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++
;--------- start ------------------------------------
;-------------------------------------------------------
START
BANK0
clrf CNT1
clrf CNT2
clrf contatore_1
clrf contatore_2
clrf PORTA ; initialize PORTA
clrf PORTB ; initialize PORTB
clrf PORTC ; initialize PORTC
BANK1
movlw 0x06
movwf ADCON1 ; Puerta A -- E/S DIgital
movlw 0x00 ; B´00000000´
movwf TRISB ; set pinsB for output
movwf TRISA ; set pinsA for output
bsf TRISC,3 ; I2C SCL pin is input
bsf TRISC,4
movlw 0x80 ; Velocidad standart con
movwf SSPSTAT ; niveles I2C
movlw 0x09 ; Velocidad del BUS I2C
movwf SSPADD ; 100 Khz
bsf PORTC,3
bsf PORTC,4
;Configuración del módulo MSSP en modo master I2C
movlw 0x28 ; Módulo MSSP en ON
movwf SSPCON
;Subrutina "DS1307_Inicializa" ;------------------------------------------------
;Configura la señal cuadrada que genera el DS1307 en su pin SQW/OUT a 1 Hz.
S_START ; Envía condición de start
movlw DS1307_Write ; Indica al DS1307 que el byte a escribir,
call write_RTC ; está en la posición 07h, que corresponde
movlw 0x07 ; al control de la señal cuadrada.
call write_RTC
movlw b'00010000' ; Escribe en el registro de control para
call write_RTC ; configurar onda cuadrada del DS1307 a 1 Hz.
movlw 0x00 ; Indica el registro de control CERO para
call write_RTC ; configurar CH del DS1307 a 0.
movlw b'00000000' ; configurar BIT 7 a 0
call write_RTC ; Clock Halt
movlw 0x02 ; Indica el registro de control DOS para
call write_RTC ; configurar Modo 12 ó 24 hrs.
movlw b'00000000' ; configurar BIT 6 a 0
call write_RTC ; Modo 24-horas
S_STOP ; Termina de enviar datos.
;----------------------------------------*******************************
;Subrutina "DS1307_Carga_Inicial" ;---------SET CLOCK--------------------
;Realiza una carga inicial en los registros internos del reloj-calendario
;DS1307 a fecha Lunes, 27 de Abril de 2008 a las 16:55:00 horas
;---------------------------------------------
;-- write to the RTC with user-entered data --
;---------------------------------------------
movlw 0x1B ; inicializa todos los datos del reloj: Año, mes,
movwf DAYS ; día, día de la semana, hora, minuto y segundo.
movlw 0x04
movwf MON
movwf DOW
movlw 0x08
movwf YRS ; Inicializa en el año 2008
movlw 0x10 ; 10 = 16
movwf HRS
movlw 0x37 ; 37 = 55
movwf MINS
clrf SECS ; Después lo graba en el DS1307 para ponerlo en marcha
call RTC_write
; Subrutina "DS1307_Lee" ;------------------------------------------------------
; Se leen las variables de tiempo del DS1307 y se guardan en los registros correspondientes
DISPLAY nop
call RTC_read ; leer clock - calendar
;---------------------------------------------
;-- display RTC data --
;---------------------------------------------
movlw high TABLA
MOVWF PCLATH
MAIN MOVF SECS,W ; Traigo el byte en formato BCD de los MINUTOS
MOVWF digi
DIGBYTE digi ; LLamada a MACRO P/ Extraccion de DIGITOS
MOVLW 0XFF ; CARGAR W con 1s
MOVWF PORTA ; para inhibir transistores
CALL DELAY_ON
MOVF DIG3,W ; Traer de macro las unidades
CALL TABLA
MOVWF PORTB ; ENVIAR DATO A SEGMENTO
BCF PORTA,0 ; Se excita la base del transistor 1
MOVLW 0X09 ; CARGO W PARA RETARDO DE 5ms *** 1A=26
CALL DELAY_OFF
MOVLW 0XFF
MOVWF PORTA ; Apago display
CALL DELAY_ON
MOVF DIG2,W
CALL TABLA
MOVWF PORTB
BCF PORTA,1 ; Se prende el transistor 2
MOVLW 0X09 ; 1A = 26 ** 09 = 24
CALL DELAY_OFF
MOVF MINS,W ; Traigo la información de HORA
MOVWF digi
DIGBYTE digi ; LLamada a MACRO P/ Extraccion de DIGITOS
MOVLW 0XFF ; CARGAR W con 1s
MOVWF PORTA ; para inhibir transistores
CALL DELAY_ON
MOVF DIG3,W ; Traer de macro las unidades
CALL TABLA
MOVWF PORTB ; ENVIAR DATO A SEGMENTO
BCF PORTA,2 ; Se excita la base del transistor 3
MOVLW 0X09 ; CARGO W PARA RETARDO DE 5ms *** 1A=26
CALL DELAY_OFF
MOVLW 0XFF
MOVWF PORTA ; Apago display
CALL DELAY_ON
MOVF DIG2,W
CALL TABLA
MOVWF PORTB
BCF PORTA,3 ; Se prende el transistor BC560 número 4
MOVLW 0X09 ; 1A = 26 ** 09 = 24
CALL DELAY_OFF
CALL DELAY_ON
GOTO DISPLAY
TABLA ADDWF PCL,1 ; .gfedcba con ULN
RETLW 0XBF ;B01000000 == 0
RETLW 0X86 ;B01111001 == 1
RETLW 0XDB ;B00100100 == 2
RETLW 0XCF ;B00110000 == 3
RETLW 0XE6 ;B00011001 == 4
RETLW 0XED ;B00010010 == 5
RETLW 0XFD ;B00000010 == 6
RETLW 0X87 ;B01111000 == 7
RETLW 0XFF ;B00000000 == 0
RETLW 0XEF ;B00010000 == 9
end