Estoy intentando simular el expansor del bus I2C PCF8574 con proteus pero no consigo hacerlo funcinar correctamente, supongo que será fallo de mi codigo.
El circuito es solo un 16f876 conectado al PCF8574 y cuatro interruptores conectados a nibble bajo.
Agradeceria si alguien puede echarme una mano para averiguar que sucede.
El siguiente paso que pretendo dar es conectar una pantalla LCD en modo 4 bits al bus I2c
El codigo que utilizo es:
;************************************************************************************************
;PROGRAMA DE PRUEBA DEL FUNCIONAMIENTO DEL PCF8574
;************************************************************************************************
list p=16f876
include "p16f876.inc"
;------------------------------------------------------------------------------------------------
org 0 ;Posicion del vector de reset
goto PRINCIPAL
org 0x50
include "var.inc"
;------------------------------------------------------------------------------------------------
Configuracion_i2c_Master ;Inicializa valores para uso de I2C en Master
;------------------------------------------------------------------------------------------------
banksel TRISC ; Selecciona Banco 1
movlw b"00011000" ; Establece lineas SDA y SCL como entradas...
iorwf TRISC,f ;..respetando los valores para otras lineas.
movlw ClockValue ; Establece velocidad I2C segun...
movwf SSPADD ; ...valor de ClockValue
bcf SSPSTAT,6 ; Establece I2C input levels
bsf SSPSTAT,SMP ; Deshabilita slew rate
clrf SSPCON2 ; Limpia control bits
banksel SSPCON ; Pasamos a direccionar Banco 0
movlw b"00101000" ; Master mode, SSP enable, velocidad segun...
movwf SSPCON ; ... Fosc/(4x(SSPADD+1))
bcf PIR1,SSPIF ; Limpia flag de eventos SSP
bcf PIR1,7 ; Limpia bit. Mandatorio por Datasheet
movlw d"10" ;Pausa de 10 centesimas de segundo para que en...
movwf Pausa ;...el arranque de tiempo a los slaves a quedar...
call HacerTiempo ;..configurados adecuadamente.
return
;------------------------------------------------------------------------------------------------
; B_Start
;
; Genera un bit de START y lo comprueba, espera hasta que se produzca y aparezca tal condicion
; en el bus
;------------------------------------------------------------------------------------------------
B_Start
banksel SSPCON2
bsf SSPCON2,SEN ; Envia Start
Espera_START
btfsc SSPCON2,SEN ; Cuando se haya dado la condicion de START se pondra a 0 el bit SEN
goto Espera_START ; Si no, seguimos esperando
banksel PIR1 ; Volvemos al banco 0
return
;------------------------------------------------------------------------------------------------
; B_Restart
;
; Genera un bit de RESTART (Repeticion de Start) y comprueba
; su aparicion, espera hasta que se produzca y aparezca tal condicion en el bus
;------------------------------------------------------------------------------------------------
B_Restart
banksel SSPCON2
bsf SSPCON2,RSEN ; Activamos la generacion de RESTART
Espera_RESTART
btfsc SSPCON2,RSEN ; Cuando se haya dado la condicion de RESTART se pondr a 0
goto Espera_RESTART ; Si no, seguimos esperando
banksel PIR1 ; Volvemos al banco 0
return
;------------------------------------------------------------------------------------------------
;Send_Ack ;EnvIa Ack
;------------------------------------------------------------------------------------------------
Send_Ack
banksel SSPCON2
bcf SSPCON2,ACKDT ; Indica mandar ACK
bsf SSPCON2,ACKEN ; Inicia secuencia de ack
Esprera_ACK
btfsc SSPCON2,ACKEN ; Cuando se haya dado la condicion de ACK se pondra a 0
goto Esprera_ACK ; Si no, seguimos esperando
banksel PIR1 ; Volvemos al banco 0
return
;------------------------------------------------------------------------------------------------
Send_Nack ;Envia Nack para finalizar recepcion
;------------------------------------------------------------------------------------------------
Send_Nack
banksel SSPCON2
bsf SSPCON2,ACKDT ; Indica mandar NACK
bsf SSPCON2,ACKEN ; Inicia secuencia de nack
Espera_NOACK
btfsc SSPCON2,ACKEN ; Cuando se haya dado la condicion de NACK se pondra a 0
goto Espera_NOACK ; Si no, seguimos esperando
banksel PIR1 ; Volvemos al banco 0
return
;------------------------------------------------------------------------------------------------
;Send_Stop ;Envia condicion de stop
;------------------------------------------------------------------------------------------------
Send_Stop
banksel SSPCON2
bsf SSPCON2,PEN ;Activa secuencia de stop
Espera_STOP
btfsc SSPCON2,PEN ; Cuando se haya dado la condicion de STOP se pondra a 0
goto Espera_STOP ; Si no, seguimos esperando
banksel PIR1 ; Volvemos al banco 0
return
;------------------------------------------------------------------------------------------------
Send_Byte ;Envia el contenido de TXBUF por i2c
;---------------------------------------------------------------------------------------
banksel TXBUF
movf TXBUF,w
movwf SSPBUF ; Inicia condicion de escritura
banksel SSPSTAT
ENVIANDO
btfsc SSPSTAT,R_W ; Para comprobar que acaba el envio
goto ENVIANDO ; Hasta que no se complete, esperando
banksel SSPCON2
movlw 0x01 ; Cargamos 0x01 en W como codigo de error por si no se recibe ACK
btfsc SSPCON2,ACKSTAT ; Chequea llegada ACK desde slave
call S_ERROR ; Si no se recibio ACK, llamamos a rutina de Error
; llevando en W el codigo
banksel PIR1
return
;------------------------------------------------------------------------------------------------
;Rec_Byte ;Recibe dato por i2c y lo mete en "DatoIn"
;------------------------------------------------------------------------------------------------
Rec_Byte
banksel SSPCON2
bsf SSPCON2,RCEN ; Inicia recepcion
LLEGANDO
btfsc SSPCON2,RCEN ; Verificamos que se ha completado la recepcion
goto LLEGANDO ; si no seguiremos esperando mientras tanto
banksel SSPBUF
movf SSPBUF,W ; Dato->W
banksel DatoIn
movwf DatoIn ; Dato->DatoIn
call Send_Ack
return
;------------------------------------------------------------------------------------------------
;
; ERROR
;
; Cargamos en TIPOERROR el codigo del Error que se haya dado
;
;------------------------------------------------------------------------------------------------
S_ERROR
bcf STATUS,RP0
movwf TIPOERROR
; goto $
return
;------------------------------------------------------------------------------------------------
;Escribir_PCF8574
;Escribe el contenido de W en el puerto del PCF8574
;------------------------------------------------------------------------------------------------
Escribir_PCF8574
movwf AUX1 ;Guarda dato
call B_Start ;Bit de start
movlw b"01000010" ;Indica escritura
movwf TXBUF
call Send_Byte ;Manda comando
movf AUX1,w ;Recupera dato
movwf TXBUF
call Send_Byte ;Manda dato
call Send_Stop ;Bit de Stop
return
;------------------------------------------------------------------------------------------------
;Leer_PCF8574
;Lee puerto y lo deja en W
;------------------------------------------------------------------------------------------------
Leer_PCF8574
call B_Start
movlw b"01000011" ;Comando lectura
movwf TXBUF
call Send_Byte
call Rec_Byte
movf DatoIn,w
call Send_Nack
call Send_Stop
return
;------------------------------------------------------------------------------------------------
;PRINCIPAL
;------------------------------------------------------------------------------------------------
PRINCIPAL
call Configuracion_i2c_Master
banksel TRISB
movlw 0xFF
movwf TRISB
banksel PORTB
P1 clrf AUX1
call Leer_PCF8574
swapf DatoIn,w
iorlw 0x0F ;Bits entrada a uno
call Escribir_PCF8574
P2 btfss PORTB,1
goto P2
P3 btfsc PORTB,1
goto P3
goto P1
goto $
;------------------------------------------------------------------------------------------------
end
Agradeceria si alguien puede echarme una mano para averiguar que sucede.
El siguiente paso que pretendo dar es conectar una pantalla LCD en modo 4 bits al bus I2c