PDA

View Full Version : Can't read sequential addresses in external EEPROM



tjkelly
- 12th February 2010, 15:48
I am using a PIC18F2420 with a Microchip 25LC1024 128k x 8 EEPROM.
To get my technique down on using the MSSP I wrote the test code below to write data to the first 2 locations in the EEPROM then to read them back.

If I do two separate reads it works but when I keep the CS low to perform a sequential read and clock the next data byte out of the EEPROM I always get FF.

What am I missing here?


'25LC1024 128k x 8 EEPROM
'PIC18F2420

CS Var PORTB.2
dummy_data Var Byte
Data_Byte1 Var Byte
Data_Byte2 Var Byte


DEFINE OSC 32 '32 Mhz Osc


Main:
TRISB=%00000000 'Set CS as an output
TRISC=%00010000 'Set SPI data in, data out and clock out
SSPSTAT = %01000000 'Sample in middle, TX rising clock edge
SSPCON1 = %00100010 'No collision/overflow, enable port,idle low,Fosc/64

High CS
Gosub Write_SPI_data
Gosub Read_SPI_data
Gosub Read_SPI_Data_Sequential
End

Write_SPI_Data:
Gosub Write_Enable
Low CS
SSPBUF = %00000010 ' Send Opcode for WRITE sequence
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send MSByte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send Middle Byte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send LSByte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000111 ' Send data byte
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
High CS

Gosub Write_Enable ' Write Enable Latch is reset after
' WRITE instruction successfully
' executed so re-enable.
Low CS
SSPBUF = %00000010 ' Send Opcode for WRITE sequence
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send MSByte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send Middle Byte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000001 ' Send LSByte of next EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00010000 ' Send data byte
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
High CS
Return


Read_SPI_Data: ' This works
Low CS
SSPBUF = %00000011 ' Send Opcode for READ sequence
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send MSByte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send Middle Byte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send LSByte of next EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send dummy data byte to clock data out of EEPROM
While SSPSTAT.0 = 0: Wend ' Wait for completion
Data_Byte1 = SSPBUF ' Get data from address 0. Should be %00000111
' and it is.
High CS ' End of first READ sequence

Low CS ' Perform next READ sequence
SSPBUF = %00000011 ' Send Opcode for READ sequence
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send MSByte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send Middle Byte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000001 ' Send LSByte of next EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send dummy data byte to clock data
' out of EEPROM.
While SSPSTAT.0 = 0: Wend ' Wait for completion
Data_Byte2 = SSPBUF ' Get data from address 1. Should be
' %00010000 and it is.
High CS ' End of second READ sequence
Return

Read_SPI_Data_Sequential: ' This doesn't work
Low CS
SSPBUF = %00000011 ' Send Opcode for READ sequence
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send MSByte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send Middle Byte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send LSByte of next EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send dummy data byte to clock next data out of EEPROM
While SSPSTAT.0 = 0: Wend ' Wait for completion
Data_Byte1 = SSPBUF ' Get data from address 0. Should be
' %00000111 and it is.
' Internal address pointer is
' automatically incremented
SSPBUF = %00000000 ' Send dummy data byte to clock data
' out of EEPROM.
While SSPSTAT.0 = 0: Wend ' Wait for completion
Data_Byte2 = SSPBUF ' Get data from address 1. Should be
' %00010000 but is %11111111
High CS ' End of READ sequence
Return

Write_Enable:
'Set the write enable latch (enable write operations)
Low CS
SSPBUF = %00000110 ' Send Opcode for WREN
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
High CS
Return

tjkelly
- 18th February 2010, 14:19
OK, after a lot of trial and error and finally getting a scope to look at some signals I determined what was going on. In the code below I found that I have to put a small delay (Pauseus 25) after each While SSPSTAT.0 = 0: Wend statement. Also had to put some delay between the WRITE ENABLE sequence and the next WRITE sequence. Also found that I can't go immediately from a WRITE into a READ without some delay between.


Write_SPI_Data:
Gosub Write_Enable
Low CS
SSPBUF = %00000010 ' Send Opcode for WRITE sequence
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send MSByte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send Middle Byte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000000 ' Send LSByte of EEPROM address
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
SSPBUF = %00000111 ' Send data byte
While SSPSTAT.0 = 0: Wend ' Wait for completion
dummy_data = SSPBUF
High CS

Melanie
- 18th February 2010, 14:46
According to the Datasheets, you need 6mS after performing a WRITE operation (be it byte or block) and upto 10mS for an Erase. Just because Transmission is completed by the Master, doesn't mean that the Slave has had time do what it needs to.