PDA

View Full Version : How to read & write to a 25aa1024 (1 Mbit SPI Bus Serial EEPROM) via 16F88



wolwil
- 28th March 2010, 09:43
I'm a newb to all of this and I bought PBP so I wouldn't have to learn assembly but I may have been wrong.

From what I can gather bit banging in PBP may be the only way to do it but I was hoping that maybe there may be another way.

For example:
Would it be possible to bit bang just the initial WRITE ENABLE SEQUENCE (WREN) of it then switch to I2C for the address/data portion and finally bit bang the WRITE DISABLE SEQUENCE (WRDI)

or

If PBP can compile assembly along side of PB and someone would be kind enough to supply me with the some example assembly and coach me through it so I understand it, that would be great too?

Thanks

wolwil
- 29th March 2010, 03:48
Well I just ordered the 24AA1025 (1024K I2C™ CMOS Serial EEPROM) and that way I will be able to use PBP's I2C capability.

However, I would still like to know how to use the 25AA1024 as I have a few lying around now that are just gunna go to waste otherwise.

Thanks

mackrackit
- 29th March 2010, 04:18
SHIFTIN/SHIFTOUT should work for the 25aa1024. You will need to look at the data sheet for the correct modes and all of that stuff.

This page has a few example about SHIFTIN/OUT and SPI.
http://www.melabs.com/resources/samples.htm

wolwil
- 30th March 2010, 02:50
SHIFTIN/SHIFTOUT should work for the 25aa1024. You will need to look at the data sheet for the correct modes and all of that stuff.

This page has a few example about SHIFTIN/OUT and SPI.
http://www.melabs.com/resources/samples.htm


Thanks for the heads up! I don't know how I missed that sample ,the "spix.bas" to begin with. I guess I just had to scroll down a little more :/

Seeing how I dont have the time to find this out for a few days... what chip should I expect to be quicker the I2C or the SPI? Both will be running off of a 4 MHz clock.

mackrackit
- 30th March 2010, 08:52
I do not know which is faster, never did a side by side or studied the specs for that.
Let us know what you find. It will be interesting to see.

wolwil
- 3rd April 2010, 18:18
I made my address a WORD because the 24AA1025 (1024K I2C™ CMOS Serial EEPROM) has a 2 byte address. So in theory this should work but as you can see the output is reading "0" in every address when it should be reading "5"

Does my code look right?

I am unsure of the PAUSE 10ms as I can't find any specs in the data sheet for the amount of time needed after each WRITE cycle. I tried commenting out the delay but still the same results. One would think if the delay was wrong I would still get a "5" in Addr0 at the very least.

Here is the schematic I used to wire up the 24AA1025 to my 16F88:
http://melabs.com/resources/pbpmanual/5_30-5_31.htm

Here is the code:


SO con 0 ' Define serial output pin
T2400 con 0 ' Set serial mode
DPIN var PORTA.0 ' I2C data pin
CPIN var PORTA.1 ' I2C clock pin
B0 var WORD ' Address
B1 var byte ' Data from first address read
B2 var byte ' Data from second address read
B3 var byte ' Second Address

For B0 = 0 To 15 ' Loop 16 times
I2CWRITE DPIN,CPIN,$A0,B0,[5] ' Write a "5" to each location
Pause 10 ' Delay 10ms after each write
Next B0

loop:

For B0 = 0 To 15 step 2 ' Loop 8 times
high 3 ' LED on to signify a Read in progress
I2CREAD DPIN,CPIN,$A0,B0,[B1,B2] ' Read 2 locations in a row
B3 = B0 + 1 ' Create second address for print
Serout SO,T2400,["Addr",#B0,":",#B1,13,10,"Addr",#B3,":",#B2,13,10] ' Print 2 locations
B3 = 0 ' Zero out B3 Variable
low 3 ' LED off to signify no read in progress
Next B0

Serout SO,T2400,[13,10] ' Print linefeed

Goto loop


And here is what I get on Hyperterm:


Addr0:0
Addr1:0
Addr2:0
Addr3:0
Addr4:0
Addr5:0
Addr6:0
Addr7:0
Addr8:0
Addr9:0
Addr10:0
Addr11:0
Addr12:0
Addr13:0
Addr14:0
Addr15:0

wolwil
- 4th April 2010, 22:21
I simplified everything and have tried everything (even tried swapping out the chip) but I cant get this EEPROM to write anything to it. Here is the new simplified code:



SO con 0 ' Define serial output pin
T2400 con 0 ' Define serial mode
cont CON %10100000 ' Define Control byte
addr CON %0000000000000111 ' 2 Byte Address of 7
B1 VAR BYTE ' Var for data being read

I2CWRITE PORTA.0,PORTA.1,cont,addr,[1] ' Send the byte 1 to address 7

PAUSE 10 ' Wait 10ms for write to complete

I2CREAD PORTA.0,PORTA.1,cont,addr,[B1] ' Read address 7 into B1

Serout SO,T2400,["Addr",#addr,":",#B1,13,10] ' Print B1's Value in DEC


Correct me if I'm wrong but the above code should work but it still just reads "0" in hyperterm like this: "Addr7:0"

I am reading 4.97V from pins 4-8 and I get 4.82V from 4-5 and 4-6 on the 24FC1025 EEPROM so my voltage is within specs. I have checked all continuity on the circuit and they all tone out.

I don't know what else to do. Please help.

wolwil
- 5th April 2010, 02:15
Pin A2 needed to be tied to VCC not VSS in order for the chip to be enabled. This however has not fixed my problem I am still getting nothing written to it.

wolwil
- 5th April 2010, 17:14
I believe I have the SDA and SCL pins going to the wrong pins on the 16F88. I have them right now going to PORTA.0 for SDA and PORTA.1 for SCL. I believe they need to be set as PORTB.1 for SDA and PORTB.4 for SCL with the 16F88. I will try this tonight and post my findings.

wolwil
- 6th April 2010, 01:03
Well I have new results but still not looking like I am writing to the chip. Now when I read I get 255 for an output and not 0. I don't know if the 24FC1025 is default all 1's or 0's. Here is the new Code:



SO con 0 ' Define serial output pin
T2400 con 0 ' Define serial mode
cont CON %10100000 ' Define Control byte
addr CON %0000000000000111 ' 2 Byte Address of 7
B1 VAR BYTE ' Var for data being read

B1 = 0 ' Set B1 to 0 to rule out 255 coming from that

I2CWRITE PORTB.1,PORTB.4,cont,addr,[20] ' Send the byte 1 to address 7

PAUSE 10 ' Wait 10ms for write to complete

I2CREAD PORTB.1,PORTB.4,cont,addr,[B1] ' Read address 7 into B1

Serout SO,T2400,["Addr",#addr,":",#B1,13,10] ' Print B1's Value in DEC


Hyperterm is giving me this:


Addr7:255
Addr7:255
Addr7:255
Addr7:255


Any help would be appreciated ;)

mackrackit
- 6th April 2010, 03:46
Table 2-1 of the data sheet Says this about pin A2


Non-Configurable Chip Select.
This pin must be hard wired to
logical 1 state (VCC). Device
will not operate with this pin
left floating or held to logical 0
(VSS)
If you are still using the schematic from MeLabs then...

The other thing I see in the data sheet is the last bit of the control byte sets Read or Write.
0 = READ
1 = WRITE


contR CON %10100000
contW CON %10100001

I2CWRITE PORTB.1,PORTB.4,contW,addr,[20]
PAUSE 10 'Is that long enough?
I2CREAD PORTB.1,PORTB.4,contR,addr,[B1]


And you may have to add this but try the above stuff first
DEFINE I2C_SLOW 1

But all the above might be a bunch of hooey. I have not used this chip...

wolwil
- 6th April 2010, 05:33
If you are still using the schematic from MeLabs then...


Nope I found that mistake of mine earlier and fixed it :o



The other thing I see in the data sheet is the last bit of the control byte sets Read or Write.
0 = READ
1 = WRITE


Yeah this one amazes me with PBP having an I2CREAD and a I2CWRITE command but yet you still have to tell it to READ or WRITE?!?!?!

Just to clarify I found this under section 5.0 saying that a READ operation should be a 1 and WRITE should be a 0


The last bit of the control byte defines the operation to
be performed. When set to a one, a read operation is
selected, and when set to a zero, a write operation is
selected.




PAUSE 10 'Is that long enough?

Yes I believe so because the 24FC1025 only has a 5ms delay needed



And you may have to add this but try the above stuff first
DEFINE I2C_SLOW 1


I tried it and got the same results, nothing but 255's.

Do you know if the 24FC1025 is flashed with all 0's or all 1's from the factory? Before I was getting %00000000 from var B1 and now I am getting %11111111 but I want to know if its actually reading that or if its a blip in the coding.

Here is the updated code:


DEFINE I2C_SLOW 1
SO con 0 ' Define serial output pin
T2400 con 0 ' Define serial mode
contR CON %10100001 ' Define Control byte
contW CON %10100000 ' Define Control byte
addr CON %0000000000000111 ' 2 Byte Address of 7
D1 CON %00000111
B0 VAR BYTE ' Var for data being read
B1 VAR BYTE ' Var for 2nd byte being read

b0 = 0
b1 = 0
I2CWRITE PORTB.1,PORTB.4,contW,addr,[D1] ' Send the byte 1 to address 7

PAUSE 10 ' Wait 10ms for write to complete

I2CREAD PORTB.1,PORTB.4,contR,addr,[B1,B0] ' Read address 7 into B1
' and address 8 into B0

Serout SO,T2400,["Addr",#addr,":",#B1," and then ",#B0,13,10] ' Print


I added a 2nd byte to check an address I have not written to and also get a 255 from that but early on in the code I set B1 and B0 to 0 and its getting changed somehow. So either I am reading all 1's from the addresses or the code is screwy.

PS sorry about the novel here, but its late and I tend to ramble when I'm tired.

Other notes:
I am using a 4MHz external clock to run the show if that matters. I will be switching to a 20MHz once I have everything working.

mackrackit
- 15th April 2010, 15:28
I picked up a couple of these 24FC1025 and I am not having any luck either.

A0 and A1 and WP are connected to VSS.
A2 connected to VDD.
10K pull up on SDA and SCL.
Tried "start/stop" sequence before and after I2C commands...

Out put to terminal is 0 no matter what.


' 18F6680 24FC1025
DEFINE OSC 20
@ __CONFIG _CONFIG1H, _OSC_HS_1H
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L

TRISF = 0
PORTF = 0
DEFINE I2C_SLOW 1
DEFINE I2C_SCLOUT 1
DPIN VAR PORTF.6 'I2C DATA PIN
CPIN VAR PORTF.7 'I2C CLOCK PIN
CONTR CON %10100001 'READ CONTROL
CONTW CON %10100000 'WRITE CONTROL
ADDR VAR WORD
DATI VAR BYTE
DATO VAR BYTE
ADDR = %0000000000000000
DATO = %11110000

START:
SEROUT2 PORTB.2, 16572,["TEST",$d,$a]
PAUSE 1000

HIGH CPIN:HIGH DPIN:LOW DPIN
I2CWRITE DPIN,CPIN,CONTW,ADDR,[DATO]
HIGH CPIN:LOW DPIN:HIGH DPIN
Pause 10

HIGH CPIN:HIGH DPIN:LOW DPIN
I2CREAD DPIN,CPIN,CONTR,ADDR[DATI]
HIGH CPIN:LOW DPIN:HIGH DPIN

Serout2 PORTB.2, 16572,["DATA IN ",BIN DATI]
SEROUT2 PORTB.2, 16572,[$d,$a]

GOTO START

mackrackit
- 15th April 2010, 20:20
I give up...

wolwil
- 15th April 2010, 22:37
I give up...


Haha! Well at least I learned the problem isn't me :D

So does anyone out there know the assembly code to make this work???

mackrackit
- 15th April 2010, 22:39
When I get back tonight I am thinking of do some sort of bit banging, maybe that will work.

Dave
- 16th April 2010, 11:31
mackrackit, Why are you using 10 k's for the pullup's? I believe the spec. says 4.7K or lower.. Might be the problem....

Dave Purola,
N8NTA

mackrackit
- 16th April 2010, 11:49
The data sheet for this part call for 10k at 100 kHz and 2k for 400 kHz and 1 MHz.

It did not work at the higher speeds so I was trying it at the slow.

wolwil
- 16th April 2010, 15:31
mackrackit, Why are you using 10 k's for the pullup's? I believe the spec. says 4.7K or lower.. Might be the problem....

Dave Purola,
N8NTA

I am using 4.7K. Sorry I forgot to mention that I was doing that different from the schematic I posted.

Did you get it to work?

mackrackit
- 16th April 2010, 17:02
I have tried several different resistor sizes and still nothing.
I think I am actually communicating with it as it "ACK" backs at me...
Here is my current mess...


' 18F6680 24FC1025
DEFINE OSC 20
@ __CONFIG _CONFIG1H, _OSC_HS_1H
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L

TRISF = 0
PORTF = 0

DPIN VAR PORTF.6 'I2C DATA PIN
CPIN VAR PORTF.7 'I2C CLOCK PIN
CONTR CON %10100001 'READ CONTROL
CONTW CON %10100000 'WRITE CONTROL
ADDR_HB VAR BYTE
ADDR_LB VAR BYTE
DATI VAR BYTE
DATO VAR BYTE
ACK VAR BIT
ADDR_HB = %00000000
ADDR_LB = %00000000
DATO = %11100000
CNT VAR BYTE
CNT = 0

START:CNT = CNT + 1
GOSUB WRITE_DATA
PAUSE 100
GOSUB READ_DATA
SEROUT2 PORTB.2, 16572,["TEST ",DEC CNT,$d,$a]
Serout2 PORTB.2, 16572,["DATA IN ",BIN DATI]
SEROUT2 PORTB.2, 16572,[$d,$a]
PAUSE 500
GOTO START

WRITE_DATA: ACK=1 :Serout2 PORTB.2, 16572,["ACK ",BIN ACK,$d,$a]
GOSUB START_ROM
SHIFTOUT DPIN,CPIN,1,[CONTW]
SHIFTIN DPIN,CPIN,0,[ACK\1]
Serout2 PORTB.2, 16572,["ACK ",BIN ACK,$d,$a]
SHIFTOUT DPIN,CPIN,1,[ADDR_HB]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[ADDR_LB]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[DATO]
SHIFTIN DPIN,CPIN,0,[ACK\1]
GOSUB STOP_ROM
PAUSE 10
RETURN

READ_DATA:
GOSUB START_ROM
SHIFTOUT DPIN,CPIN,1,[CONTR]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[ADDR_HB]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[ADDR_LB]
SHIFTIN DPIN,CPIN,0,[ACK\1]
GOSUB START_ROM
SHIFTOUT DPIN,CPIN,1,[CONTR]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTIN DPIN,CPIN,0,[DATI\8]
GOSUB STOP_ROM
PAUSE 10
RETURN

START_ROM:
HIGH CPIN:HIGH DPIN:LOW DPIN:RETURN
STOP_ROM:
HIGH CPIN:LOW DPIN:HIGH DPIN:RETURN

wolwil
- 17th April 2010, 04:46
I changed the Control Byte for the read and the write from this:

contR CON %10100001
contW CON %10100000

to this:

contR CON %10100011
contW CON %10100010

Thinking that because A2 is held high for it to operate then the control bit for A2 should also be a 1... here is the new code:

DEFINE I2C_SLOW 1
SO con 0 ' Define serial output pin
T2400 con 0 ' Define serial mode
contR CON %10100011 ' Define Control byte
contW CON %10100010 ' Define Control byte
addr CON %0000000000000111 ' 2 Byte Address of 7
addr2 CON %0000000000001000 ' 2 Byte Address of 8
D1 CON %00000111
B0 VAR BYTE ' Var for data being read
B1 VAR BYTE ' Var for data being read

B0 = 0
B1 = 0
I2CWRITE PORTB.1,PORTB.4,contW,addr,[D1] ' Send the byte 1 to address 7

PAUSE 10 ' Wait 10ms for write to complete

I2CREAD PORTB.1,PORTB.4,contR,addr,[B1] ' Read address 7 into B1
I2CREAD PORTB.1,PORTB.4,contR,addr2,[B0] ' Read address 8 into B0

Serout SO,T2400,["Addr",#addr,":",#B1," and then Addr",#addr2,":",#B0,13,10] ' Print B1's Value in DEC

this is the output from hyperterm:

Addr7:2 and then 2

Like I said I don't know what it means but it sure is different then what I was getting.

Any thoughts as to why it now is reading a "2" and not 255 or 0??? Its almost like it read the last 2 bits of the write control byte as if the write command wrote the last 2 bits of the control byte to the EEPROM.


UPDATE:
I just switched the control byte to be:

contR CON %10100001
contW CON %10100010
and got this as an output (Note the "6" in Address 8 to begin and then it get over written to "255" the next go around):


Addr7:2 and then Addr8:6
Addr7:2 and then Addr8:255
Addr7:2 and then Addr8:255
Addr7:2 and then Addr8:255
Addr7:2 and then Addr8:255
also I know I'm writing to it because in the example output above I read address 6 with it too (not shown in the code but I added it after posting) and I was reading "255" every time. So this tells me that I am writing a "6" to address 8 but then on the second loop it gets over written/erased to "255" but the "2" in address 7 remains constant and in memory. Now keep in mind that no where in my code do I try to write to address 8 it just happens, more than likely from an over flow from the write to address 7. So basically the byte I am trying to write to 7 gets split into a "2" in address 7 and a "6" in address 8 then address 8 gets overwritten on the 2nd loop to a "255".

and when I do the control byte like this:

contR CON %10100011
contW CON %10100000
I get this (the same as having both A2 bits set to 1):

Addr7:2 and then Addr8:2
Addr7:2 and then Addr8:2
Addr7:2 and then Addr8:2

ScaleRobotics
- 17th April 2010, 06:34
Sorry, read the data sheet wrong. Nevermind

wolwil
- 17th April 2010, 19:45
Whoops it dawned on me what I am doing by changing that Bit. I guess that my novice understanding of this made me stumble upon the fact that I am now writing and reading from a different Chip Select, but seeing how I only have the one chip I dont understand how its reading/writing chip 01 when it should be chip 00. :confused:

So I guess where I was calling it the A2 bit its actually the A0 bit that I was changing.

mackrackit
- 17th April 2010, 20:05
How do you have pins A0 and A1 connected?

I have not had a chance to work on this today yet so I do not have any new news.

wolwil
- 17th April 2010, 20:11
How do you have pins A0 and A1 connected?

I have not had a chance to work on this today yet so I do not have any new news.


Tied to ground.

Dave
- 17th April 2010, 22:48
mackrackit, You can't use Shiftout and Shiftin for an I2C bus driven part. That is why you had no luck using it with a 24FC1025... It requires the pullup resistor for communicating the ACK signal back to the processor. Shiftout keeps the pin in an active state wghich ever it is... I recently posted code for talking to 24LC1025's here on the forum... Why not just use it for a starting point... I don't remember which thread it was in reply to but I believe it had to do with I2C....

Dave Purola,
N8NTA

wolwil
- 17th April 2010, 23:42
Dave,

I've searched through all the posts on the 24LC1025 and didn't find any code you posted but I found code that is basically the same as what I have tried already. If you can find the thread you were thinking of that would be great.

The only thing I have not tried is changing is my pullups from 4.7k to 2k and trying to write to it 1 page at a time but if I cant byte-write to begin with I'm sure the page write will not work either. I will try changing the Pullups tonight and see what happens.

mackrackit
- 18th April 2010, 00:51
I got the idea for shifting here.
http://www.rentron.com/PicBasic/i2c_communication.htm

Reading back over my code and data sheet I see some things are backwards. Maybe ...

Never did find that code posting. Found lots of others for different parts.

wolwil
- 18th April 2010, 01:21
Everything is the same as before with the new pullup values of 2.2K...back to the drawing board :mad:

I am going to be out of town for the next week so I wont be able to test anything new but I will be on here checking if any new ideas/breakthroughs come up.

Dave
- 18th April 2010, 22:59
wolwil, Here it is again incase you didn't find it. Maxpages is set for 1023 x the number of 24LC1025's you have connected. The routine saves the last storage pointer in the last 2 locations of the last 24LC1025. Block is incremented once for each page. Before you start a clean write you would set block to 0 which is the first page. When you want to read back the data then you would call READ_WRITE_BLK1025 and block would have the last address written..

This routine is rock solid and I use it for accessing 4 x 24LC1025's for a total of over 4 gigabits of memoy to record Azmnuth,Elevation,East/West/Up/Down Sensor data and control flag information for about 2 months at 1 minute intervals... I hope this helps...



CNTRL_BYTE CON $A0 'CONTROL BYTE FOR 24LC1025 I2C EEPROM MEMORY (A0/A1 USED FOR CHIP SELECT)
MAX_PAGES CON 4095 'MAXIMUM MEMORY STORAGE PAGES,(32 BYTES/MINUTE x 4 MINUTES x PAGES = TOTAL MINUTES)

'************************************************* ********************
RW_EEPROM1025: 'READ FROM or WRITE TO SERIAL EEPROM
'************************************************* ********************
IF READ_WRITE = 1 THEN 'WRITE 128 BYTE BLOCK TO EEPROM
IF BLOCK <> 0 THEN 'IF STARTING NEW PASS DON'T READ OLD LOCATION
READ_WRITE = 0 'SET FOR BLOCK READ
GOSUB READ_WRITE_BLK1025 'READ FROM SERIAL EEPROM NEXT AVAILABLE STORAGE BLOCK
READ_WRITE = 1 'SET FOR BLOCK WRITE
ENDIF
DEVICE = BLOCK / 512 'SELECT WHICH PHYSICAL ADDRESS BOUNDRY & EEPROM
ADDRESS = BLOCK << 7 'CALCULATE 12C ADDRESS TO STORE DATA TO
CNTROL_BYTE = CNTRL_BYTE 'COPY CONTROL BYTE
CNTROL_BYTE.1 = DEVICE.1 'SET LSB OF HARDWARE ADDRESS
CNTROL_BYTE.2 = DEVICE.2 'SET MSB OF HARDWARE ADDRESS
CNTROL_BYTE.3 = DEVICE.0 'SET 64K BLOCK BIT
INTCON.7 = 0 'CLEAR GLOBAL INTERRUPT
I2CWRITE SDA,SCL,CNTROL_BYTE,ADDRESS,[STR STOR_DATA\128] 'SAVE DATA TO 12C
WRITEOCCURED = 1
INTCON.7 = 1 'SET GLOBAL INTERRUPT
PAUSE 6 'ALLOW TIME FOR I2C WRITE ~5Ms.
BLOCK = BLOCK + 1 'INCREMENT FOR NEXT AVAILABLE BLOCK TO WRITE
BLOCK = BLOCK MIN MAX_PAGES 'LIMIT TO n BLOCKS OF 128 BYTES
GOSUB READ_WRITE_BLK1025 'WRITE TO or READ FROM SERIAL EEPROM LAST STORAGE BLOCK
ELSE
DEVICE = BLOCK / 512 'SELECT WHICH PHYSICAL ADDRESS BOUNDRY & EEPROM
ADDRESS = BLOCK << 7 'CALCULATE 12C ADDRESS TO STORE DATA TO
CNTROL_BYTE = CNTRL_BYTE 'COPY CONTROL BYTE
CNTROL_BYTE.1 = DEVICE.1 'SET LSB OF HARDWARE ADDRESS
CNTROL_BYTE.2 = DEVICE.2 'SET MSB OF HARDWARE ADDRESS
CNTROL_BYTE.3 = DEVICE.0 'SET 64K BLOCK BIT
INTCON.7 = 0 'CLEAR GLOBAL INTERRUPT
I2CREAD SDA,SCL,CNTROL_BYTE,ADDRESS,[STR READ_DATA\128] 'LOAD IN ENTIRE BLOCK
WRITEOCCURED = 1
INTCON.7 = 1 'SET GLOBAL INTERRUPT
ENDIF
RETURN

'************************************************* ********************
READ_WRITE_BLK1025: 'WRITE TO or READ FROM SERIAL EEPROM NEXT AVAILABLE STORAGE BLOCK
'************************************************* ********************
ADDRESS = 65534 'POINT TO LAST STORED DATA(WORD) ADDRESS
DEVICE = MAX_PAGES / 512 'SELECT WHICH PHYSICAL ADDRESS BOUNDRY & EEPROM
CNTROL_BYTE = CNTRL_BYTE 'COPY CONTROL BYTE
CNTROL_BYTE.1 = DEVICE.1 'SET LSB OF HARDWARE ADDRESS
CNTROL_BYTE.2 = DEVICE.2 'SET MSB OF HARDWARE ADDRESS
CNTROL_BYTE.3 = DEVICE.0 'SET 64K BLOCK BIT
IF READ_WRITE = 1 THEN
INTCON.7 = 0 'CLEAR GLOBAL INTERRUPT
I2CWRITE SDA,SCL,CNTROL_BYTE,ADDRESS,[BLOCK.LOWBYTE,BLOCK.HIGHBYTE] 'WRITE DATA POINTER TO 12C
WRITEOCCURED = 1
INTCON.7 = 1 'SET GLOBAL INTERRUPT
PAUSE 6 'ALLOW TIME FOR I2C WRITE ~5Ms.
ELSE
INTCON.7 = 0 'CLEAR GLOBAL INTERRUPT
I2CREAD SDA,SCL,CNTROL_BYTE,ADDRESS,[BLOCK.LOWBYTE,BLOCK.HIGHBYTE] 'READ DATA POINTER FROM 12C
WRITEOCCURED = 1
INTCON.7 = 1 'SET GLOBAL INTERRUPT
ENDIF
RETURN


Dave Purola,
N8NTA

mackrackit
- 19th April 2010, 11:40
Hi Dave,
Thanks for posting your code. I also found my problem...

My problem is "I am a newbe!!!".
I forgot PORTF.6 on the 18F6680 is an analog pin. :o
RTFD RTFD RTFD

For what it is worth.. When I take care of the analog issue I can read the part with SHIFTIN/OUT. I can not write to the part that way yet. Still have a timing problem I guess. It may not be worth messing with other than an exercise in coding.

wolwil
- 19th April 2010, 19:10
CNTRL_BYTE CON $A0 'CONTROL BYTE FOR 24LC1025 I2C EEPROM MEMORY (A0/A1 USED FOR CHIP SELECT)


Maybe this is where I am getting confused... you have the control byte being $A0 which is basically saying to write to the 24LC1025 seeing how the read write bit in that is a 0 like this "10100000" but the you say in your comment that the A0/A1 is for chip select...So in this following line of code where I have the $A0 is that the 8 bit control byte or just the Chip Select portion of it???



I2CREAD PORTB.1,PORTB.4,$A0,addr,[B1]


See I thought if I wanted to write to chip select A1 I needed to use $A2 or in binary like this %10100010 and if I wanted to read from it I needed to use $A3 or in binary like this %10100011.

Every combination to read and write to all 4 Chips:

%10100000 or $A0 = Write to A0 (Pins A0 & A1 Tied Low)
%10100001 or $A1 = Read from A0
%10100010 or $A2 = Write to A1 (Pins A0 Tied Low & A1 Tied High)
%10100011 or $A3 = Read from A1
%10100100 or $A4 = Write to A2 (Pins A0 Tied High & A1 Tied Low)
%10100101 or $A5 = Read from A2
%10100110 or $A6 = Write to A3 (Pins A0 and A1 Tied High)
%10100111 or $A7 = Read from A3

So with me having both A0 and A1 Pins Tied to ground I should be using the first 2 options when trying to read/write to the chip or am I just way off on this???

Am I incorrect in my thinking of what PBP is calling the Control Byte???

mackrackit
- 19th April 2010, 21:23
10100000
Is the R/W bit. Leave it as "0" and PBP takes care of parsing it to a "1" if needed.

10100000
Are the A0 and A1 bits. If pins A0 and A1 are connected to the zero rail leave as zero. Mixing and matching on or the other or both gives the four combination's for up to four chips on the same bus.

10100000
Is the bit to set to read or write to the first or second block.

mackrackit
- 19th April 2010, 21:59
Here is how to read and write to a Serial EEPROM using SHIFTIN/SHIFTOUT.
Using a 24FC1025.

Why???? Why not???

I have the DATA and CLOCK pins pulled up with 2.7k resistors.
Follow the code with the data sheet to understand what is going on.


DEFINE OSC 20

DPIN VAR PORTB.2 'I2C DATA PIN
CPIN VAR PORTB.1 'I2C CLOCK PIN
CONT1 CON %10100001 'READ CONTROL
CONT0 CON %10100000 'WRITE CONTROL
ADDR_HB VAR BYTE
ADDR_LB VAR BYTE
DATOW VAR BYTE
ACK VAR BIT
ADDR_HB = 0'%00000000
ADDR_LB = 0'%00000000
DATOW VAR BYTE
CNT VAR BYTE
CNT = 0

START:
CNT = CNT + 1
DATOW = 245
GOSUB WRITE_DATA
PAUSE 10
GOSUB READ_DATA
LCDOUT $FE,1,"TEST ",DEC CNT
lcdout $FE,$C0,"DATA IN ",DEC DATI
lcdout $FE,$90,"LB ",DEC ADDR_LB
PAUSE 250
GOTO START

WRITE_DATA:
ADDR_LB = ADDR_LB + 1
GOSUB START_ROM
SHIFTOUT DPIN,CPIN,1,[CONT0]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[ADDR_HB]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[ADDR_LB]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[DATOW\8]
SHIFTOUT DPIN,CPIN,1,[%1\1]
GOSUB STOP_ROM
PAUSE 10
RETURN

READ_DATA:
GOSUB START_ROM
SHIFTOUT DPIN,CPIN,1,[CONT0]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[ADDR_HB]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTOUT DPIN,CPIN,1,[ADDR_LB]
SHIFTIN DPIN,CPIN,0,[ACK\1]
GOSUB START_ROM
SHIFTOUT DPIN,CPIN,1,[CONT1]
SHIFTIN DPIN,CPIN,0,[ACK\1]
SHIFTIN DPIN,CPIN,0,[DATI\8]
SHIFTOUT DPIN,CPIN,1,[%1\1]
GOSUB STOP_ROM
PAUSE 10
RETURN

START_ROM:
HIGH CPIN:HIGH DPIN:LOW DPIN:RETURN
STOP_ROM:
HIGH CPIN:LOW DPIN:HIGH DPIN:RETURN

Make sure you have ANALOG turned off!! :eek:

wolwil
- 20th April 2010, 02:47
Thanks for the code guys! I will try it out on sunday when I get back.

wolwil
- 25th April 2010, 23:05
Well I was able to get your code to work. I noticed when I was reading before using the I2CREAD I was getting all 255's and now I am reading using your code and still getting all 255's where ther is no data written so that is telling me that I was getting the I2CREAD to work before. I am now reading through all memory locations looking for the data I wrote to it before using the I2CWRITE command to try and figure out where it wrote it and why. Once this finishes I will post my findings and thoughts.

Thanks again for the code.

PS:
I have not tried Dave's code yet

UPDATE:
I found the written data from my old code in Block 1 of the EEPROM. I am going to go back to the old code I had and try and make it work. I will post my findings

wolwil
- 26th April 2010, 00:42
First and foremost Thank You, Thank You, Thank You for all of your help guys I really do appreciate it.

Here is the working Code:


' Define serial output pin
SO con 0

' Define serial mode
T2400 con 0

' 2 Byte Address Vars
addr1 var word
addr2 var word
addr3 var word

' Vars for data being written
D1 Var Byte
D2 Var Byte
D3 Var Byte

' Vars for data being read
B1 VAR BYTE
B2 VAR BYTE
B3 VAR BYTE

' Set Data Bytes
D1 = 7
D2 = 6
D3 = 5

' Set Address Bytes
addr1 = 1
addr2 = 2
addr3 = 3

I2CWRITE PORTB.1,PORTB.4,$A0,addr1,[D1] ' Write a 1 to address 1
PAUSE 10 ' Wait 10ms for write to complete
I2CWRITE PORTB.1,PORTB.4,$A0,addr2,[D2] ' Write a 2 to address 2
PAUSE 10 ' Wait 10ms for write to complete
I2CWRITE PORTB.1,PORTB.4,$A0,addr3,[D3] ' Write a 3 to address 3
PAUSE 10 ' Wait 10ms for write to complete

I2CREAD PORTB.1,PORTB.4,$A0,addr1,[B1] ' Read address 1 into B1
I2CREAD PORTB.1,PORTB.4,$A0,addr2,[B2] ' Read address 2 into B2
I2CREAD PORTB.1,PORTB.4,$A0,addr3,[B3] ' Read address 3 into B3

Serout SO,T2400,["Addr",#addr1,":",#B1," and then Addr",#addr2,":",#B2," and then Addr",#addr3,":",#B3,13,10] ' Print B1's Value in DEC



and it's out putting this to Hyperterm:


Addr1:7 and then Addr2:6 and then Addr3:5
Addr1:7 and then Addr2:6 and then Addr3:5
Addr1:7 and then Addr2:6 and then Addr3:5

The problem I had in the beginning was I had the SDA/SCL Pins wrong and I did not have the A2 pin Tied to +5V but after correcting those I had my control byte misunderstood and thats why it would not work. After changing the control byte back to $A0 with the A2 held High and the propper pins chosen for SDA and SCL it now works like it should.

I hope this thread saves everyone a ton of time in the future with these chips I know I sure learned a ton from this little experiance :)