How to read & write to a 25aa1024 (1 Mbit SPI Bus Serial EEPROM) via 16F88
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
I can't WRITE to the I2C What am I doing wrong?
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:
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:
Code:
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
I found 1 problem with my circuit.
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.
I think I found another issue with the circuit.
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.
Getting "255" from the read and not "0"
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:
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:
Code:
Addr7:255
Addr7:255
Addr7:255
Addr7:255
Any help would be appreciated ;)
I made a break through I just don't know what it means :D
I changed the Control Byte for the read and the write from this:
Code:
contR CON %10100001
contW CON %10100000
to this:
Code:
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:
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:
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:
Code:
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):
Code:
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:
Code:
contR CON %10100011
contW CON %10100000
I get this (the same as having both A2 bits set to 1):
Code:
Addr7:2 and then Addr8:2
Addr7:2 and then Addr8:2
Addr7:2 and then Addr8:2
Changed the Pullups to 2.2K and still no change
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.
Mackrackit your code works :D
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
Finally got it to work!!!
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:
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:
Code:
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 :)