esta es la rutina i2c para hacer funcioar el pcf8583
;**************************************************************************
; I2CLOW.INC
;
; Autor: Mikel Etxebarria
; (c) Microsystems Engineering (Bilbao)
;
;Conjunto de rutinas de bajo nivel que permiten la transmisión/recepción
;a nivel de byte entre dispositivos I2C. Igualmente generan las condiciones
;de inicio y de stop así como detectar/generar los bits ACK y NACK. Estas
;rutinas están pensadas para ser utilizadas con elementos de la gama media
;16cXX
;
;
;***************************************************************************
;Definición de registros empleados por el software de interface al bus I2C
;con los dispositivos de la gama media 16cxx
;
Clkout equ CLKIN >> 2 ;Frecuencia de trabajo (Clkin/4)
_4uS_Delay set (Clkout/.250000) ;Constante para 4 uS
_47uS_Delay set (Clkout/.212766) ;Constante para 4.7 uS
_5uS_Delay set (Clkout/.200000) ;Constante para 5 uS
CBLOCK I2c_var ;Reserva de memoria a partir de I2c_var que
;será la primera libre disponible
DataByte ;Dato que va a ser transmitido
BitCount ;Nº de bits a transmitir/recibir (0

Bus_status ;Registro de estado del bus I2C
Bus_Control ;Registro de control del bus I2C
DelayCount ;Variable de temporización
DataByteCopy ;Copia del dato a transmitir
ENDC ;Fin de la reserva
;***************************************************************************
;Definición de las líneas del bus I2C
;***************************************************************************
#define _SCL porta,1
#define _SDA porta,0
#define _SCL_TRIS porta,1
#define _SDA_TRIS porta,0
#define _WRITE_ 0
#define _READ_ 1
;***************************************************************************
;Definición de los bits del registro de estado del bus I2C
;***************************************************************************
#define _Bus_Busy Bus_status,0 ;Bus I2C ocupado
#define _Abort Bus_status,1 ;Comunicación abortada
#define _Txmt_Progreso Bus_status,2 ;Transmisión en progreso
#define _Rcv_Progreso Bus_status,3 ;Recepción en progreso
#define _Txmt_Acabada Bus_status,4 ;Transmisión finalizada
#define _Rcv_Acabada Bus_status,5 ;Recepción finalizada
#define _Fatal_Error Bus_status,6 ;Error en comunicación
#define _ACK_Error Bus_status,7 ;Error en bit ACK
;***************************************************************************
;Definición de los bits del registro de control del bus I2C
;***************************************************************************
#define _Ultimo_Byte Bus_Control,2 ;Indica si es el último byte a recibir
;**************************************************************************
; Macro de propósito general
;**************************************************************************
LIBERA_BUS MACRO
bsf status,rp0 ;Selecciona banco 1
bsf _SDA ;SDA en triestado
bsf _SCL ;SCL en triestado
bcf status,rp0 ;Selecciona banco 0 de dato
bcf _Bus_Busy
ENDM
;**************************************************************************
; Inicia_Bus
;
;Inicialización del Bus I2C
;**************************************************************************
Inicia_Bus:
bcf status,rp0 ;Selecciona página 0 de datos
;movf portb,W ;Carga puerta B
;andlw 0x3f
movf porta,W ;Carga puerta B
andlw b"00111100"
movwf porta ;Pone a 0 los latch internos
;de las líneas SCL y SDA
LIBERA_BUS ;Coloca SDA y SCL en triestado
clrf Bus_Control ;Borra registro de control
clrf Bus_status ;Borra registro de estado
return
;**************************************************************************
; Txt_Start_Bit
;
;Transmisión de la condición de inicio
;**************************************************************************
Txt_Start_Bit:
bsf status,rp0 ;Selecciona página 1
bsf _SDA ;Pone como entradas las señales SDA y
bsf _SCL ;SCL que al estar con resistencia
;pull-up, las líneas SDA y SCL se man-
;tienen a "1"
call Delay4uS
bcf _SDA ;La señal SDA se configura como salida
;que saca el "0" del latch interno ha-
;ciendo que la línea SDA caiga a "0"
;mientras SCL se mantiene a "1" (con-
;dición de inicio)
call Delay47uS
bcf status,rp0 ;Selecciona banco 0 de dato
bsf _Bus_Busy ;Activa flag de bus ocupado
return
;**************************************************************************
; TxT_Stop_Bit
;
;Transmisión de la condición de stop
;**************************************************************************
Txt_Stop_Bit:
bsf status,rp0 ;Selecciona página 1 de datos
bcf _SCL ;Las señales SCL y SDA se programan
bcf _SDA ;como salidas. El contenido de los
;latch internos hace que las líneas
;SCL y SDA se pongan a "0"
bsf _SCL ;Esta señal se programa ahora como
;entrada en alta impedancia que, gra-
;cias a las pull-up internas, pone a
;"1" la línea SCL.
call Delay4uS
bsf _SDA ;Esta señal se programa ahora como
;entrada en alta impedancia que, gra-
;cias a las pull-up internas, genera un
;flanco de subida en la línea SDA (con-
;dición de stop).
call Delay47uS ;Asegura que no se envía una nueva
;condición de start justo después de la
;de stop.
bcf status,rp0 ;Selecciona banco 0 de dato
bcf _Bus_Busy ;Tras el stop se considera que el bus
;está libre, borrando el bit de estado
return
;**************************************************************************
; Txt_Abort
;
;Abortar la transmisión
;**************************************************************************
Txt_Abort:
call Txt_Stop_Bit ;Transmite la condición de stop
bsf _Abort ;Activa flag en registro de estado
return
;**************************************************************************
; Txt_Byte
;
;Transmisión de un byte de datos
;El Byte a transmitir debe cargarse previamente en el registro DataByte
;**************************************************************************
Txt_Byte:
movf DataByte,w ;Realiza una copia del byte a trans-
movwf DataByteCopy ;mitir (pos.0x0e)
bsf _Txmt_Progreso ;Activa flag de transmisión en curso
bcf _Txmt_Acabada ;Desactiva flag de finalización
movlw 0x08
movwf BitCount ;Número de bits a transmitir
bsf status,rp0 ;Selecciona página 1 de datos
TxtNextBit: clrwdt ;Refresco del WDT
bcf _SCL ;Pone a "0" la línea SCL
rlf DataByteCopy,f ;Desplaza bit de más peso
bcf _SDA ;Pone a "0" la l¡nea SDA
btfsc status,C ;Testea bit a sacar sito en el carry
bsf _SDA ;Saca "1" por la línea SDA poniendo
;la señal SDA como entrada pull-up
call Delay47uS
bsf _SCL ;Pone a "1" la línea SCL poniendo
;la señal SCL como entrada pull-up
call Delay4uS
decfsz BitCount,f ;Decrementa contador de bits
goto TxtNextBit
;Chequeo del bit ACK
bcf _SCL ;Pone a "0" la línea SCL
bsf _SDA ;Pone a "1" la línea SDA para detec-
;tar cuándo el slave la pone a "0"
call Delay47uS
bsf _SCL ;Pone a "1" línea de reloj
call Delay4uS
bcf status,rp0 ;Selecciona página 0 de datos
btfsc _SDA ;La señal SDA debe estar a "0" envia-
;do por el slave
goto TxtErrorAck
bsf status,rp0 ;Selecciona página 1 de datos
bcf _SCL ;Pone a "0" la línea SCL
bcf status,rp0 ;Selecciona banco 0 de dato
bcf _Txmt_Progreso ;Borra flag de transmisión en curso
bsf _Txmt_Acabada ;Activa flag de fin de transmisión
bcf _ACK_Error ;Bit ACK okey
bcf _Bus_Busy ;Flag de que el bus está libre
return
TxtErrorAck: LIBERA_BUS
bcf _Txmt_Progreso ;Borra flag de transmisión en curso
bcf _Txmt_Acabada ;Borra flag de fin de transmisión
bsf _ACK_Error ;Activa bit de error ACK (NACK)
return
;***************************************************************************
; RcvByte
;
;Recepción de un byte desde el slave
;El dato recibido se almacena en el registro DataByte.
;El bit _Ultimo_Byte del registro de control determina si se espera recibir
;más bytes desde el slave, en cuyo caso se le manda ACK o, si es el último,
;en cuyo caso se envía NACK.
;***************************************************************************
RcvByte:
bsf _Rcv_Progreso ;Flag de recepción en curso
bcf _Rcv_Acabada ;Desactiva flag de fin de recepción
movlw 0x08 ;Carga el contador de bits a recibir
movwf BitCount
RcvNextBit:
clrwdt ;Refresco del WDT
bsf status,rp0 ;Selección de página 1 de datos
bcf _SCL ;Pone a "0" la línea de reloj
bsf _SDA ;Pone a "1" la línea de datos
call Delay47uS
bsf _SCL ;El reloj pasa a "1". El bit de datos
;es puesto por el slave
call Delay4uS
bcf status,rp0 ;Seleciona página 0 de datos
bcf status,C ;Pone el flag carry a "0"
btfsc _SDA ;Chequea el nivel en línea de datos
bsf status,C ;Está a "1", activa el carry
rlf DataByte,f ;Desplaza a la izda. (primero el bit
;de más peso)
decfsz BitCount,f ;Decrementa contador de bits a recibir
goto RcvNextBit
;El Master genera ACK si no es el último byte a recibir. Si es el último
;se genera NACK y a continuación se debe generar la condición de stop.
bsf status,rp0 ;Selecciona página 1 de datos
bcf _SCL ;Pone a "0" la línea de reloj
bcf _SDA ;Pone a "0" la línea de datos (ACK)
btfsc _Ultimo_Byte ;Determina si es el último byte
bsf _SDA ;Pone a "1" la línea de datos (NACK)
call Delay47uS
bsf _SCL ;Pone a "1" la línea de reloj
call Delay4uS
bcf _SCL ;Pone a "0" la línea de reloj
bcf status,rp0 ;Selecciona banco 0 de dato
bcf _Rcv_Progreso ;Desactiva flag de recepción en curso
bsf _Rcv_Acabada ;Activa flag de fin de recepción
bcf _ACK_Error ; ACK ok
return
;****************************************************************************
;Rutinas de temporización de propósito general
;****************************************************************************
;
Delay5uS:
movlw ((_5uS_Delay-5)/3+1)
delay:
movwf DelayCount
decfsz DelayCount,f
goto $-1
return
Delay47uS: movlw ((_47uS_Delay)-8/3+1)
goto delay
Delay4uS: movlw ((_4uS_Delay)-8/3+1)
goto delay