Buenas...
Aca posteo lo que programe(he sudado bastante pa lograrlo) para leer y escribir una EEPROM de 8kbits(24LC08B) desde un 16F877A en Assembler a FOSC = 20Mhz utilizando el modulo I2C de este PIC.
Lo que hace es grabar un dato en la posicion 0 de la EEPROM , y luego leerlo y mostrar el dato leido en el PuertoB del PIC.
<span class="texto_mini">Codigo:</span>[hr /
]
;Made by Bruno Fascendini
;bipus24hs@hotmail.com
LIST P=PIC16F877A
#include <p16F877a.INC>
ERRORLEVEL -302
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; CONSTANTES:
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define CLOCK D"0"
#define STROBE D"2"
#define SCL D"3"
#define SDA D"4"
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;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.
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DIRL EQU 0X20
DIRH EQU 0X21
DATO EQU 0X22 ;temporar. byte a enviar/dato leido
flag EQU 0X24
cuenta EQU 0X25
CONTA0 EQU 0X26
CONTA1 EQU 0X27
DATASSP EQU 0x70
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ORG 0X0000
GOTO INICIO
ORG 0X0004
return
ORG 0X0020
INICIO BANK0
BSF STATUS,RP0
MOVLW 0x06 ;PINS DEL PUERTO A Y PUERTO E TODOS DIGITALES.
MOVWF ADCON1
CLRW
MOVWF TRISA
BANK0
CLRF PORTA
BSF STATUS,RP0
MOVLW 0X00
MOVWF TRISB
BANK0
CLRF PORTB
BSF STATUS,RP0
MOVLW B"00011000"
MOVWF TRISC
BANK0
MOVLW B"00010000"
MOVWF PORTC
BSF STATUS,RP0
MOVLW 0X00
MOVWF TRISD
BANK0
CLRF PORTD
BSF STATUS,RP0
MOVLW 0X00
MOVWF TRISE
BANK0
CLRF PORTE
call i2c_init ;configurar y encender I2C
clrf DIRH ;cargar paginas de 24LC08B en las cuales escribir
clrf DIRL ;cargar direccion de 24LC08B en las cuales escribir
movlw 0xA0
movwf DATASSP ;cargar dato a escribir en la 24LC08B
call WriteI2CByte
btfss flag,0
goto errorcom
call DEMORA ;dar 10ms a que termine la escritura
clrf DIRH ;cargar paginas de 24LC08B de las cuales leer
clrf DIRL ;cargar direccion de 24LC08B de las cuales leer
call ReadI2CByte
btfss flag,0
goto errorcom
movlw .1 ;escritura y lectura OK. encender RA0, mostrar dato leido en PuertoB y loop eterno
movwf PORTA
movf DATO,w
movwf PORTB
nop
goto $-1
errorcom movlw .3 ;error de escritura o lectura, encender RA0 y RA1 y loop eterno
movwf PORTA
nop
goto $-1
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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
movlw b"00011000"
banksel TRISC ;banco 1
iorwf TRISC,F
movlw b"00001011" ;.11 para 400khz @ 20 mhz
movwf SSPADD ;400 khz @ 20 mhz
clrf SSPSTAT
movlw b"00101000"
bcf STATUS,RP0 ;banco 0
movwf SSPCON
CLRF PIR1
call i2c_idle
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_idle
bsf STATUS,RP0 ;banco 1
btfsc SSPSTAT,R_W
goto $-1
movf SSPCON2,w
andlw 0x1F
btfss STATUS,Z
goto $-3
bcf STATUS,RP0 ;banco 0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_start
call i2c_idle
bsf STATUS,RP0 ;banco 1
bsf SSPCON2,SEN
btfsc SSPCON2,SEN
goto $-1
bcf STATUS,RP0 ;banco 0
btfss PIR1,SSPIF
goto $-1
bcf PIR1,SSPIF
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_restart
bsf STATUS,RP0 ;banco 1
bsf SSPCON2,RSEN
btfsc SSPCON2,RSEN
goto $-1
bcf STATUS,RP0 ;banco 0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_read
call i2c_idle
bsf STATUS,RP0 ;banco 1
bsf SSPCON2,RCEN ;activar modo lectura
btfsc SSPCON2,RCEN ;termino la recepcion?
goto $-1 ;no, esperar
btfss SSPSTAT,BF ;dato disponible en SSPBUF para ser leidos?
goto $-1 ;no, esperar
bcf STATUS,RP0 ;banco 0
movf SSPBUF,W
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
bsf STATUS,RP0 ;banco 1
btfsc SSPSTAT,R_W ;esperar a que termine el envio
goto $-1
btfss SSPCON2,ACKSTAT ;checkear ack
goto okack
bsf SSPCON2,PEN ;error ack. enviar STOP
bcf STATUS,RP0 ;banco 0
return ;volver con flag= 0 error
okack bcf STATUS,RP0 ;banco 0
btfss PIR1,SSPIF ;esperar finalizacion del noveno clock
goto $-1
bcf PIR1,SSPIF
bsf flag,0 ;volver con flag = 1 OK!
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_sendack
bsf STATUS,RP0 ;banco 1
bcf SSPCON2,ACKDT
bsf SSPCON2,ACKEN
bcf STATUS,RP0 ;banco 0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_sendnack
bsf STATUS,RP0 ;banco 1
bsf SSPCON2,ACKDT
bsf SSPCON2,ACKEN
bcf STATUS,RP0 ;banco 0
return
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
i2c_stop
bsf STATUS,RP0 ;banco 1
bsf SSPCON2,PEN ;enviar STOP
bcf STATUS,RP0 ;banco 0
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
rlf DIRH,W
andlw b"00000110" ;solo 2 bits de paginas admitidas para esta eeprom. Asegurar bit0 =0 (write)
iorlw b"10100000" ;insertar identificador de la EEPROM(1010) en el mensaje
movwf DATO ;cargar byte en variable a enviar(DATO)
call i2c_write
btfss flag,0
return ;volver. error de escritura
movf DIRL,w
movwf DATO
call i2c_write
btfss flag,0
return ;volver. error de escritura
movf DATASSP,w
movwf DATO ;cargar en DATO
call i2c_write
btfss flag,0
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:
;DATO ;dato leido
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ReadI2CByte
call i2c_start ;enviar START, esperar a que se libere el BUS
rlf DIRH,W
andlw b"00000110" ;solo 2 bits de paginas admitidas para esta eeprom. Asegurar bit0 =0 (write)
iorlw b"10100000" ;insertar identificador de la EEPROM(1010) en el mensaje
movwf DATO ;cargar byte en variable a enviar(DATO)
call i2c_write
btfss flag,0
return ;volver. error de escritura
movf DIRL,w
movwf DATO
call i2c_write
btfss flag,0
return ;volver. error de escritura
call i2c_restart ;enviar RESSTART
rlf DIRH,W
andlw b"00000110" ;solo 2 bits de paginas admitidas para esta eeprom.
iorlw b"10100001" ;insertar identificador de la EEPROM(1010) en el mensaje. Asegurar bit0 =1 (Read)
movwf DATO ;cargar byte en variable a enviar(DATO)
call i2c_write
btfss flag,0
return ;volver. error de escritura
call i2c_read
call i2c_sendnack
call i2c_stop
return ;flag = 1 OK!
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
END
Espero les sea de utilidad. Exitos!