hola,he modificado el programa de BrunoF y puesto al final como unas instrucciones de uso para facilitar el entendimiento.
LIST P=16F876
#include "p16F876.INC"
__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF ;&_WRT_ENABLE_OFF
ERRORLEVEL -302
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; CONSTANTES:
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define OK D'0'
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;Memoria EEPROM
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; MACROS
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BANK0 MACRO
BCF STATUS,RP0
BCF STATUS,RP1
ENDM
BANK1 MACRO
BSF STATUS,RP0
BCF STATUS,RP1
ENDM
BANK2 MACRO
BSF STATUS,RP1
BCF STATUS,RP0
ENDM
BANK3 MACRO
BSF STATUS,RP1
BSF STATUS,RP0
ENDM
;GPR: GENERAL PURPOSE REGISTERS
;0x20 -> 0x47 Reservados Memoria cartel.
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CBLOCK 0X20
DIRL
DIRH
DATO ;temporar. byte a enviar/dato leido
flag
cuenta
CONTA0
CONTA1
DATASSP
ENDC
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ORG 0
GOTO INICIO
ORG 5
INICIO BANK1
MOVLW 0X00
MOVWF TRISB
MOVLW B'00011000'
MOVWF TRISC
BANK0
CLRF PORTB
call i2c_init ;configurar y encender I2C
clrf DIRH ;cargar paginas de 24LCxx en las cuales escribir ;8º
clrf DIRL ;cargar direccion de 24LCxx en las cuales escribir ;9º
movlw 0xA0
movwf DATASSP ;cargar dato a escribir en la 24LCxx ;10º
call WriteI2CByte
btfss flag,0
goto INICIO ;si ha habido algun fallo durante la grabacion,repite el programa.
call DEMORA ;dar 10ms a que termine la escritura
clrf DIRH ;cargar paginas de 24LCxx de las cuales leer
clrf DIRL ;cargar direccion de 24LCxx de las cuales leer
call ReadI2CByte ;lee direccion cargada en DIRH y DIRL
btfss flag,0
goto INICIO ;si ha habido algun fallo durante la lectura,repite el programa.
movf DATO,w
movwf PORTB ;escribe dato leido en PORTB ;31º
goto $-1 ;salta un paso atras
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DEMORA movlw .55
movwf CONTA0
RET1 movlw .181
movwf CONTA1
RET2 nop
nop
decfsz CONTA1,1
goto RET2
decfsz CONTA0,1
goto RET1
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_init BANK1
movlw b'00011000' ;RC3 y RC4 como entradas ;1º
iorwf TRISC,F
movlw b'00001001' ;.9 para 100khz @ 4 mhz ;2º
movwf SSPADD
clrf SSPSTAT ;borra registro banderas del SSP ;3º
BANK0
movlw b'00101000' ;activa modo I2C en modo master y ;4º
movwf SSPCON ;selecciona frecuencia mediante formula: clock=Fosc/(4*(SSPADD+1))
CLRF PIR1 ;5º
call i2c_idle
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_idle BANK1
btfsc SSPSTAT,R_W ;espera a que termine la transmision ;6º
goto $-1
movf SSPCON2,w ;espera a que SEN,RSEN,PEN,RCEN,ACKEN ;7º
andlw 0x1F ;se pongan todos a cero
btfss STATUS,Z
goto $-3
BANK0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_start call i2c_idle
BANK1
bsf SSPCON2,SEN ;activa condicion de arranque ;12º
btfsc SSPCON2,SEN ;espera a que se ponga a cero
goto $-1
BANK0
btfss PIR1,SSPIF ;espera a que la condicion de START haya sido completada ;13º
goto $-1
bcf PIR1,SSPIF ;borra flag de la interrupcion anterior
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_restart BANK1
bsf SSPCON2,RSEN
btfsc SSPCON2,RSEN
goto $-1
BANK0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_read call i2c_idle
BANK1
bsf SSPCON2,RCEN ;activar modo lectura ;27º
btfsc SSPCON2,RCEN ;termino la recepcion?
goto $-1 ;no, esperar
btfss SSPSTAT,BF ;dato disponible en SSPBUF para ser leidos? ;28º
goto $-1 ;no, esperar
BANK0
movf SSPBUF,W ;29º
movwf DATO
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_write bcf flag,0 ;inicializar flag como "error"
call i2c_idle
movf DATO,w ;mover DATO a W
movwf SSPBUF ;cargar dato en buffer I2C ;16º
BANK1
btfsc SSPSTAT,R_W ;esperar a que termine el envio ;17º
goto $-1
btfss SSPCON2,ACKSTAT ;checkear ack ;18º
goto okack
bsf SSPCON2,PEN ;error ack. enviar STOP
BANK0
return ;volver con flag= 0 error
okack BANK0
btfss PIR1,SSPIF ;esperar finalizacion del noveno clock
goto $-1
bcf PIR1,SSPIF
bsf flag,0 ;volver con flag = 1 OK!
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_sendack BANK1
bcf SSPCON2,ACKDT
bsf SSPCON2,ACKEN
BANK0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_sendnack 30º
BANK1
bsf SSPCON2,ACKDT
bsf SSPCON2,ACKEN
BANK0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_stop BANK1
bsf SSPCON2,PEN ;enviar STOP 25º
BANK0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;WriteI2CByte
;DIRH<1:0> ;paginas de la eeprom en las cuales grabar
;DIRL ;direccion baja de la posicion de eeprom en las cuales grabar
;DATASSP ;dato a grabar
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WriteI2CByte
call i2c_start ;enviar START, esperar a que se libere el BUS
movlw b'10100000' ;"1010"= identificador EEPROM. "000" = numero EEPROM "0"= Write ;14º
movwf DATO
call i2c_write
btfss flag,OK
return
movf DIRH,W
andlw b'01111111' ;solo 7 bits de paginas admitidas para esta eeprom.
movwf DATO ;cargar byte en variable a enviar(DATO) ;19º
call i2c_write ;20º
btfss flag,OK
return ;volver. error de escritura
movf DIRL,W
movwf DATO ;21º
call i2c_write ;22º
btfss flag,OK
return ;volver. error de escritura
movf DATASSP,W ;23º
movwf DATO ;cargar en DATO
call i2c_write ;24º
btfss flag,OK
return ;volver. error de escritura
call i2c_stop
return ;flag = 1 OK!
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;ReadI2CByte
;DIRH<1:0> ;paginas de la eeprom de las cuales leer
;DIRL ;direccion baja de la posicion de eeprom de las cuales leer
;devuelve:
;DATASSP ;dato leido
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ReadI2CByte call i2c_start ;enviar START, esperar a que se libere el BUS
movlw b'10100000' ;1010=identificador EEPROM 000= numero EEPROM 0=write
movwf DATO ;cargar byte en variable a enviar(DATO)
call i2c_write
btfss flag,OK
return ;volver. error de escritura
movf DIRH,W
andlw b'01111111' ;solo 7 bits admitidos para esta EEPROM
movwf DATO
call i2c_write
btfss flag,OK
return
movf DIRL,W
movwf DATO
call i2c_write
btfss flag,OK
return ;volver. error de escritura
call i2c_restart ;enviar RESSTART
movlw b'10100001' ;1010=identificador EEPROM 000= numero EEPROM 1=read 26º
movwf DATO ;cargar byte en variable a enviar(DATO)
call i2c_write
btfss flag,OK
return ;volver. error de escritura
call i2c_read
call i2c_sendnack
call i2c_stop
return ;flag = 1 OK!
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CurrentI2CRead
call i2c_start ;enviar START, esperar a que se libere el BUS
movlw b'10100001' ;1010=identificador EEPROM 000= numero EEPROM 1= read
movwf DATO ;cargar byte en variable a enviar(DATO)
call i2c_write
btfss flag,OK
return ;volver. error de escritura
call i2c_read
call i2c_sendnack
call i2c_stop
return ;flag = 1 OK!
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
END
PROGRAMA WriteI2CByte y readI2cByte de BrunoF INTERPRETADO POR GROUNDMAN
he repasado el programa y lo he interpretado de esta forma para entendelo un poco mejor.este programa lo que hace es grabar
en la direccion 00h de una eeprom externa mediante I2C el dato A0h y luego lo lee para visualizarlo en PORTB
;aqui se graba el dato
;1º pon a 1 los pin RC3 y RC4 de trisc,para configurarlos como entradas.
;2º carga valor b'00001001' en SSPADD para el baud rate generator.100KHZ ,frecuencia=Fosc/(4*(SSPADD+1))
;3º borra el registro de banderas SSPSTAT
;4º carga valor b'00101000' en SSPCON para seleccionar I2C modo maestro,
;5º borra PIR1
;6º comprueva el bit R_W de SSPSTAT y si es 1=trasnmision en prograso,espera a que se ponga a 0=transmision terminada.
;7º espera a que los bits SEN,RSEN,PEN,RCEN,ACKEN de SSPCON2 esten todos a 0
;8º carga en DIRH la direccion alta a acceder de la memoria
;9º carga en DIRH la direccion alta a acceder de la memoria
;10º carga el dato a escribir en DATASSP
;11º vuelve a ejecutar los pasos 6º, 7º
;12º activa SEN de SSPCON2 "condicion de arranque"y espera a que se ponga a 0.
;13º espera a que se produzca interrupcion por condicion de start completada.(flag SSPIF de PIR1) y borrar el flag
;14º carga valor identificador de eeprom b'10100000' en registro DATO
;15º vuelve a ejecutar los pasos 6º, 7º
;16º carga el valor contenido del registro DATO en SSPBUF
;17º espera a que R_W de SSPSTAT se ponga a 0.(fin del envio)
;18º comprueva bit ACKSTAT de SSPCON2,y si es 1 activa PEN de SSPCON2"STOP a causa de un error",si es 0
esperar finalizacion del noveno clock SSPIF de PIR1 y borrar el flag
;19º mete direccion byte alto en DATO.
;20º vuelve a ejecutar los pasos 6º,7º,16º,17º,18º
;21º mete direccion byte bajo en DATO.
;22º vuelve a ejecutar los pasos 6º,7º,16º,17º,18º
;23º carga DATASSP en DATO
;24º vuelve a ejecutar los pasos 6º,7º,16º,17º,18º
;25º activa PEN de SSPCON2 "STOP"
;aqui se lee el dato
;ejecuta pasos 6º,7º,12º,13º,14º,20º,19º,20º,21º,20º,12º
;26º carga valor identificador de eeprom b'10100001' en registro DATO el bit 1=(lectura)
;20º,6º,7º
;27º activa modo lectura y espera a que termine la recepcion
;28º recepcion completada
;29º carga en DATO el valor leido de la eeprom
;30º activa ACKDT y ACKEN del registro SSPCON2
;ejecuta paso 25º
;saca el dato por PORTB
ESPERO NO HABERME EQUIVOCADO. SALUDOS.