Hola gente:
He ensamblado el programa y todo ok.
Ahora el problema es que aún no tengo la 24lc256 fisicamente y me he puesto a simularlo en el PROTEUS, pero me da error.
Le he incluido unas lineas de más para saber si el error era de escritura o lectura y para que haga un loop escribiendo y leyendo en bucle cada 1 segundo.
Lo he puesto a 20mhz, .11 en para 400khz en registro , incluso lo he modificado para 100khz pero es peor.
Me da errores erráticos, a veces de escritura (PORTA,1), a veces OK (PORTA,0) , y a veces de lectura (PORTA,2) .
Se debe esto al simulador del proteus? O hay algo que falla en el programa? Le he puesto las resistencias correspondientes de 4k7 a las lineas SDA , SCL y el WP a masa junto con los A0-A2.
Aqui os dejo el programa , a ver si veis algo anormal.
LIST P=16F877A
#include "p16F877A.INC"
__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC & _BODEN_OFF &_LVP_OFF &_CPD_OFF ;&_WRT_ENABLE_OFF
ERRORLEVEL -302
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
; CONSTANTES:
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define CLOCK D'0'
#define STROBE D'2'
#define SCL D'3'
#define SDA D'4'
#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.
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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
PDel0 equ 0x28; (registro)
PDel1 equ 0x29 ;(registro)
PDel2 equ 0x2A; (registro)
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
ini
CLRF PORTB
CLRF PORTA
call DEMORA1s
clrf DIRH ;cargar paginas de 24LC08B en las cuales escribir
clrf DIRL ;cargar direccion de 24LC08B en las cuales escribir
movlw 0x55
movwf DATASSP ;cargar dato a escribir en la 24LC08B
call WriteI2CByte
btfss flag,0
goto errorescr
call DEMORA ;dar 10ms a que termine la escritura
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 errorlect
;escritura y lectura OK. encender RA0, mostrar dato leido en PuertoB y loop eterno
bsf PORTA,0
movf DATO,w
movwf PORTB
call DEMORA1s
goto ini
errorescr bsf PORTA,1
call DEMORA1s
goto ini
errorlect bsf PORTA,2
call DEMORA1s
goto ini
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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 .11; b'00001011' ;.9 para 100khz a 4mhz , .11 para 400khz @ 20 mhz
movwf SSPADD ;
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
bsf PORTC,0
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
call i2c_write
btfss flag,OK ;;volver. error de escritura
return
bcf PORTC,0
movf DIRH,W
andlw b'01111111' ;solo 7 bits de paginas admitidas para esta eeprom.
movwf DATO ;cargar byte en variable a enviar(DATO)
call i2c_write
btfss flag,OK
return ;volver. error de escritura
movf DIRL,W
movwf DATO
call i2c_write
btfss flag,OK
return ;volver. error de escritura
movf DATASSP,W
movwf DATO ;cargar en DATO
call i2c_write
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
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!
DEMORA1s movlw .14 ; 1 set numero de repeticion (C)
movwf PDel0 ; 1 |
PLoop0 movlw .72 ; 1 set numero de repeticion (B)
movwf PDel1 ; 1 |
PLoop1 movlw .247 ; 1 set numero de repeticion (A)
movwf PDel2 ; 1 |
PLoop2 clrwdt ; 1 clear watchdog
decfsz PDel2, 1 ; 1 + (1) es el tiempo 0 ? (A)
goto PLoop2 ; 2 no, loop
decfsz PDel1, 1 ; 1 + (1) es el tiempo 0 ? (B)
goto PLoop1 ; 2 no, loop
decfsz PDel0, 1 ; 1 + (1) es el tiempo 0 ? (C)
goto PLoop0 ; 2 no, loop
PDelL1 goto PDelL2 ; 2 ciclos delay
PDelL2 clrwdt ; 1 ciclo delay
return ; 2+2 Fin.
;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
END