Y vuelve Pibe a la carga con sus memorias SPI !
En este caso llenamos TODA la memoria con un dato (AA) desde la posicion 00 00 a la FF FF
Si lo simulamos en el Proteus, le damos a pausa y luego click derecho sobre la 25lc512 y seleccionamos la ultima opción (creo que es "ver memoria")
podremos ver como va llenando la memoria.
Lo interesante es ver como escribe por páginas, solo dándole la dirección de comienzo en
los dos bytes ADDRHIGH y ADDRLOW y haciendo un conteo hasta 128 (cada página contiene 128 bytes)
si el contador llega a cero entonces pasa a la próxima página (sumando 128 al ADDRLOW y acarreo al ADDRHIGH)
y así hasta el final de la memoria. Simulado en Proteus tarda aproximadamente 17,5 segundos.
Hay que tener especial cuidado de llamar a la rutina
write_in donde inicializamos la memoria externa, enviándole
comandos de habilitación de escritura, etc.
Luego se envia el dato o datos llamando a la rutina
data_in por cada
dato que cargamos (solo cargar W con el dato y llamar a data_in) para al final de la escritura (aunque no hayamos llenado
toda la página ) llamamos a la rutina
write_out que le indica que hemos acabado de escribir en esa página.
De no indicarle el fin de escritura seguiría escribiendo datos y al llegar a 128 volvería a escribir desde 00 en la
misma página , sobreescribiendo los datos ya guardados.
El programa hace una pausita de 5ms por página en la cual escribe los 128 bytes que tiene en su propio buffer en el array
Aqui os dejo el esquema Proteus
prueba512.DSNy el HEX para los más vagos
PRII.HEX;ESCRITURA de una 25LC512 o 25AA512
LIST p=16f877A ;definimos micro
#include <p16f877A.inc> ;definiciones del micro
__config _CP_OFF & _XT_OSC & _WDT_OFF & _PWRTE_OFF & _LVP_OFF & _BODEN_OFF ; configuraciones del micro
;La idea es trabajar con un cristal/resonador ceramico de 10 mhz para el micro
ERRORLEVEL -302 ;suppress "not in bank 0" message
ERRORLEVEL -203 ;suppress message
ERRORLEVEL -305 ;suppress message
ERRORLEVEL -205 ;suppress message
;****************************************************
;Definición de pines del micro
;****************************************************
#define SCK PORTC,3 ; OUT Salida SCLK del periférico SPI
#define SDI PORTC,4 ; IN Entrada SDI del periférico SPI
#define SDO PORTC,5 ; OUT Salida SDO del periférico SPI
#define CSMEM PORTC,6 ; OUT Salida CS para seleccionar la 25AA512
;******************************************************************************
; Definición de variables del programa
;******************************************************************************
CBLOCK 0X20
tmp1
cont
rxdata ; buffer del dato recibido
ADDRHIGH ; byte de dirección alta
ADDRLOW ; byte de dirección baja
;Variables misceláneas
PDel0; equ 0x51 ; variable para demora
PDel1; equ 0x52 ; variable para demora
loops; equ 0x54 ; variable para demora
ENDC
; Macros de cambio de bancos
BANK0 MACRO
bcf STATUS, RP0
bcf STATUS, RP1
ENDM
BANK1 MACRO
bsf STATUS, RP0
bcf STATUS, RP1
ENDM
BANK2 MACRO
bcf STATUS, RP0
bsf STATUS, RP1
ENDM
BANK3 MACRO
bsf STATUS, RP0
bsf STATUS, RP1
ENDM
ORG 00h
goto Inicio
Inicio
BANK1
movlw b'00010000'
movwf TRISC ;
movlw 0x80 ; set up spi port, SPI master,
movwf SSPSTAT ; cke = 0 (mode 1,1)
clrf PIE1 ; disable peripheral interrupts
clrf INTCON ; disables all interrupts
BANK0
clrf PCLATH ; nos aseguramos que el bit 3 de PCLATH sea 0
CLRF PORTA ; inicializamos puertos
CLRF PORTB
CLRF PORTC ;
CLRF PORTD
CLRF PORTE
bsf CSMEM ; nos aseguramos que el CS de la memoria esté en nivel alto
movlw 0x07
movwf CMCON ; apagamos el módulo comparador
movlw 0x31 ; SPI master, clk/16, ckp=1
movwf SSPCON ; SSPEN enabled
Principal
MOVLW 0XAA ;dato a escribir en toda la memoria
MOVWF tmp1
movlw .128
movwf cont ; un contador para saber que llegamos a final de página
Envio_datos
;Ya podemos iniciar el envio de datos, inicializando el modulo SPI
call write_in
;Y rápidamente ir metiéndole los datos a rxdata
movf tmp1,w
call data_in ; llamamos a la carga de dato
decfsz cont
goto $-3
movlw .128
movwf cont ;reiniciamos contador
;Hemos llenado una página de 128 bytes con AA como dato
call write_out ; y salimos de la sesion de escritura de la memoria
call inc_pagina ;incrementamos una página ( +128 )
movf ADDRHIGH,w ;vamos a ver que no se haya pasado de vueltas y nos sobreescriba desde el principio
sublw 0x00 ;
btfss STATUS,Z ;
goto Envio_datos
movf ADDRLOW,w ;vamos a ver que no se haya pasado de vueltas
sublw 0x00 ;
btfss STATUS,Z ;
goto Envio_datos
;Hemos llenado toda la memoria con AA
stop
bsf PORTC,7 ; encendemos led para saber que llegamos al final de la memoria
goto stop
;**************************************************************************
; Rutinas de acceso a la EEPROM externa 25AA512 por módulo SPI hardware
;**************************************************************************
;Cada página consta de 128 bytes
;512 páginas en total
;MAPA DE MEMORIA EXTERNA
;____________________________________________________________________________________________
;
; 01 -- -- -- -- -- -- -- FF
; 00 00
;
; FF FF
;__________________________________________________________________________________________
write_in
;Send the write enable sequence (WREN)
bcf CSMEM ; clear the chip select (active)
movlw 0x06 ; load WREN sequence
call output ; call the SPI output routine
bsf CSMEM ; set the chip select line
;Send the write status register sequence (WRSR)
;Deshabilitamos los bits protectores
bcf CSMEM ; clear the chip select line
movlw 0x01 ; clear all status register
call output ; call the SPI output routine
movlw 0x00 ; load up zero to send
call output ; call the SPI output routine
bsf CSMEM ; set the chip select line
;Wait the required 5mS for the write cycle timer Twc
call delay ; call the delay subroutine
;Send the write enable sequence (WREN)
bcf CSMEM ; clear the chip select (active)
movlw 0x06 ; load WREN sequence
call output ; call the SPI output routine
bsf CSMEM ; set the chip select line
;Send the read status register sequence (RDSR)
bcf CSMEM ; clear the chip select line
movlw 0x05 ; load RDSR sequence
call output ; call the SPI output routine
call output ; read the data in status reg.
bsf CSMEM ; set the chip select line
;Send the write sequence (WRITE)
bcf CSMEM ; clear the chip select line
movlw 0x02 ; load WRITE sequence
call output ; call the SPI output routine
;****************************************************************
movf ADDRHIGH,W ; load high address byte
call output ; call the SPI output routine
;****************************************************************
movf ADDRLOW,W ; move the address into w
call output ; call the SPI output routine
;****************************************************************
return
data_in
call output ; call the SPI output routine
return
write_out
bsf CSMEM ; set the chip select line
call delay
return
;*******************SPI output subroutine***********************
output
movwf SSPBUF ; place data in send buffer
loop1
bsf STATUS,RP0 ; set to bank 1
btfss SSPSTAT,BF ; has data been received?
goto loop1 ; loop if not received yet
bcf STATUS,RP0 ; set to bank 0
movf SSPBUF,W ; empty the receive buffer
movwf rxdata;rxdata ; put received byte into rxdata
retlw 0 ; return from subroutine
; 250 x 400nS x 50 = 5mS (plus overhead)
delay
movlw 0x32 ; move 50 decimal into w
movwf PDel0 ; move 50 decimal into temp1
dec1
movlw 0xFA ; move 250 decimal into w
movwf PDel1 ; move 250 decimal into temp2
dec2
decfsz PDel1,1 ; decrement temp2, skip if zero
goto dec2 ; goto decrement 2 if not zero
decfsz PDel0,1 ; decrement temp1, skip if zero
goto dec1 ; goto decrement 1 if not zero
retlw 0 ; return both locations = 0
inc_pagina
movlw 0x80
addwf ADDRLOW
btfsc STATUS,C
incf ADDRHIGH,1
return
END