Hola a todos, tengo una duda ya baje un programita que comunica a 2 16f877a por medio de i2c master y slave, ahora checando el programa me surge una duda el sppadr que memoria usa y cuantas direcciones tengo, son un tipo de memoria ram de 256 bytes o como se mandeja, quiero tener unos 20 bytes o en su defecto unos 16 bits para poder saber el estado de una tarjeta, les pongo los codigos espero me puedan orientar.
master
PROGP CLRF MSGIN
CLRF MSGOUT
; MOVLW d"10" ;PAUSA de 10 centésimas de segundo para que en...
; MOVWF PAUSA ;...el arranque de tiempo a los slaves a quedar...
; CALL HacerTiempo ;..configurados adecuadamente.
MLoop
;ENVIO DE UN BYTE AL SLAVE
;Se ha de guardar el byte que se quiere transmitir en "MSGOUT" y
;la dirección del Slave en "DIRSL". Tras esto solo hay que llamar
;a la subrutina "Enviar"
MOVLW B"10101010" ;dato cualquiera por I2C que metemos en
MOVWF MSGOUT ;"MSGOUT" para envío por I2C
MOVLW B"01111000" ;Establece dirección de envío..
MOVWF DIRSL ;..es decir, dirección del slave
CALL Enviar ;Envía el dato de "MSGOUT" al Slave
;PETICION DE UN BYTE DE DATOS AL SLAVE
;Se da la dirección del Slave en "DIRSL". Tras esto solo hay que llamar
;a la subrutina "Recibir" y se obtendrá el dato en "MSGIN"
MOVLW b"01111000" ;Establece dirección de solicitud..
MOVWF DIRSL ;..es decir, dirección del slave
CALL Recibir ;Toma dato del Slave...
MOVF MSGIN,W ;... a través de "MSGIN"...
MOVWF PORTB ;...y lo muestra por PORTB (Leds)
GOTO MLoop
;*********************************************************************************
; SUBRUTINAS
;*********************************************************************************
; --------------------------------------------------------------------------------------
Enviar ;Envía un mensaje (comando) almacenado en "MSGOUT" al Slave cuya dirección
;se ha de encontrarse en la variable "DIRSL"
;---------------------------------------------------------------------------------------
;Guardamos copia de algunos registros
MOVWF W_TEMP ;Hace copia de W
MOVF STATUS,W ;Hace copia de registro de estado
MOVWF ST_TEMP
StEnv CALL Send_Start ;Envía condición de inicio
CALL CheckIdle ;Espera fin evento
MOVF DIRSL,W ;Dirección esclavo
CALL Send_Byte ;Envía dirección y orden de escritura
CALL CheckIdle ;Espera fin evento
CALL WrtAckTest ;Verifica llegada ACK
BANKSEL SSPCON2
BCF SSPCON2,ACKSTAT ;limpia flag ACK
XORLW 0X01
BTFSC STATUS,Z ;Chequea si llegó ACK
GOTO StEnv ;No. Reintentamos envío
BANKSEL MSGOUT ;Si. Seguimos con envío dato
MOVF MSGOUT,W ;Lo deja en W para que la subrutina Send_Byte lo envíe
CALL Send_Byte ;envía por i2c
CALL CheckIdle ;Espera fin evento
CALL Send_Stop ;Envia condición de parada
CALL CheckIdle ;Espera fin evento
;Restauramos las copias de los registros
MOVF ST_TEMP,W ;Restaura las copias de registros
MOVWF STATUS ;registro de estado
MOVF W_TEMP,W ;registro W
RETURN
slave
PROGP CLRF MSGIN
CLRF MSGOUT
MLoop movlw b"10011001" ;dato cualquiera por I2C que metemos en
movwf MSGOUT ;"MSGOUT" para cuando el Master se lo pida
movf MSGIN,W ;Muestra por port B (leds)...
movwf PORTB ;...el ultimo valor enviado por el Master
goto MLoop
;*********************************************************************************
; SUBRUTINAS
;*********************************************************************************
; --------------------------------------------------------------------------------------
State1: ; Operación de escritura, ultimo byte ha sido
movlw b"00001001" ; de dirección, el buffer está lleno.
xorwf TEMP,W
btfss STATUS,Z ; Estamos en el primer estado?
goto State2 ; No, checkeamos siguiente estado
call ReadI2C ; SI. Hacemos un read SSPBUF (para vaciar buffer).
; El Hardware se ocupa de mandar Ack
return
State2: ; Operación de escritura, ultimo byte ha sido
movlw b"00101001" ; de datos, el buffer está lleno.
xorwf TEMP,W
btfss STATUS,Z ; Estamos en el segundo estado?
goto State3 ; NO, checkeamos siguiente estado
call ReadI2C ; SI, Tomamos el byte del SSP.
;Aquí tenemos en W el valor del dato recibido
movwf MSGIN
return
State3: ; Operación de lectura, ultimo byte ha sido
movlw b"00001100" ; de dirección, el buffer está vacío
xorwf TEMP,W
btfss STATUS,Z ; Estamos en el tercer estado?
goto State4 ; NO, checkeamos siguiente estado
;Aquí debemos poner en W el valor del dato a enviar (solicitado por el master)
movf MSGOUT,W
call WriteI2C ; SI, escribimos el byte en SSPBUF
return
State4: ; Operación de lectura, ultimo byte ha sido
movlw b"00101100" ; de datos, el buffer está vacío
xorwf TEMP,W
btfss STATUS,Z ; Estamos en el cuarto estado?
goto State5 ; NO, checkeamos siguiente estado
;Aquí debemos poner en W el valor del dato a enviar (solicitado por el master)
movf MSGOUT,W
call WriteI2C ; SI, escribimos el byte en SSPBUF
return
State5:
movlw b"00101000" ; Se ha recibido un NACK mientras se transmitían...
banksel TEMP
xorwf TEMP,W ; ..datos al master. Lo lógica del Slave..
btfss STATUS,Z ; ..se resetea en este caso. R_W = 0, D_A = 1
goto I2CErr ; y BF = 0
return ; Si no estamos en State5, entonces es
; que algo fue mal
I2CErr nop ; Algo fue mal
return
;---------------------------------------------------------------------
WriteI2C ;Usada por SSP_Handler para escribir datos en bus I2C
;---------------------------------------------------------------------
banksel SSPCON
movwf SSPBUF ; Escribe el dato en W
bsf SSPCON,CKP ; Libera el reloj
return
;---------------------------------------------------------------------
ReadI2C ;Usada por SSP_Handler para escribir datos en bus I2C
;---------------------------------------------------------------------
banksel SSPBUF
movf SSPBUF,W ; Toma el byte y lo guarda en W
return
;-------------------------------------------------------------------------------
QUEINT ;RUTINA DE INTERRUPCIÓN. Se ocupa de los eventos I2C
;-------------------------------------------------------------------------------
;Guardamos copia de algunos registros
movwf W_TEMP ;Hace copia de W
movf STATUS,W ;Hace copia de registro de estado
movwf ST_TEMP
;Chequeamos si la interrupción es por evento I2C. En caso positivo llamamos
;a la rutina de proceso del evento
banksel PIR1
btfss PIR1,SSPIF ;Ha ocurrido un evento SSP? (I2C)
goto IntNoSSP ;No. entonces será por otra cosa. Saltamos.
call SSP_Handler ;Si. Procesamos el evento. Si se reciben ordenes, quedarán
;registradas en "MSGIN". Se enviarán las ordenes
;guardadas en "MSGOUT".
banksel PIR1
bcf PIR1,SSPIF ;Limpiamos el flag
goto Rest
IntNoSSP ;Aquí se gestionan interrupciones que no son por SSP
;..........
; En caso de necesitarse, poner aquí la rutina de gestión de interrupciones
; que no sean por bus I2C
;..........
Rest ;Restauramos las copias de los registros
movf ST_TEMP,W ;Restaura las copias de registros
movwf STATUS ;registro de estado
movf W_TEMP,W ;registro W
retfie