Trouble writing Prop EEPROM
Steve Hicks (N5AC)
Posts: 20
I'm sure I'm doing something stupid here, but I've been looking at this for about 6 hours and I can't seem to figure out what I'm doing wrong... any ideas?· I have some fixed data (stored in a DAT block) that I am trying to write over at runtime, but just in the EEPROM (I'm not concerned about RAM).· Here's the relevant snippet of my code:
I make a call to PrepareI2C and then I call a series of EEWriteLong's.· This uses the i2cobject.spin by James Burrows.· What I get out is this:
So,·in the first write, the EEPROM data is 75, I try to write a 104 and I get a 75 back ... after receiving an ACK... any clues about what I'm doing wrong?· I have to believe it is something simple about the timing or how I am doing the start-up call.· I don't need to add a %1 to the EEPROM_Addr to enable the write bit do I (for the R/W bit?)· ... I tried that and it didn't work either...
Thanks,
Steve
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Steve, N5AC
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 _stack = 50 i2cSCL = 28 i2cSDA = 29 EEPROM_Addr = %1010_0000 EEWAIT = 400_000 OBJ i2c: "i2cObject" PRI PrepareI2C ' setup i2cobject i2c.init(i2cSDA, i2cSCL, true) i2c.Start if i2c.devicePresent(EEPROM_Addr) <> true debug.str(string("EEPROM NOT PRESENT? ")) else debug.str(string("EEPROM PRESENT -- PROGRAMMING MODE")) debug.crlf PRI EEWriteLong(addr, data) EEByte(addr, data & $FF) EEByte(addr+1, (data >> 8) & $FF) EEByte(addr+2, (data >> 16) & $FF) EEByte(addr+3, (data >> 24) & $FF) PRI EEByte(addr, data) | ack, data2 data2 := i2c.readLocation(EEPROM_ADDR, addr, 16, 8) waitcnt(EEWAIT + cnt) debug.str(string("B4 = ")) debug.str(NUM.ToStr(data2,NUM#DEC)) debug.str(string(", DATA = ")) debug.str(NUM.ToStr(data,NUM#DEC)) debug.str(string(", ACK = ")) ack := i2c.writeLocation(EEPROM_ADDR, addr, data, 16, 8) waitcnt(EEWAIT + cnt) debug.str(NUM.ToStr(ack,NUM#DEC)) debug.str(string(", NEW = ")) data2 := i2c.readLocation(EEPROM_ADDR, addr, 16, 8) waitcnt(EEWAIT + cnt) debug.str(NUM.ToStr(data2,NUM#DEC)) debug.crlf
I make a call to PrepareI2C and then I call a series of EEWriteLong's.· This uses the i2cobject.spin by James Burrows.· What I get out is this:
[color=#ff0000][color=#ff0000][color=#ff0000]B4 = 75, DATA = 104, ACK = 0, NEW = 75 B4 = 0, DATA = 1, ACK = 0, NEW = 0 B4 = 0, DATA = 0, ACK = 0, NEW = 0 B4 = 0, DATA = 0, ACK = 0, NEW = 0 [/color][/color][/color]
So,·in the first write, the EEPROM data is 75, I try to write a 104 and I get a 75 back ... after receiving an ACK... any clues about what I'm doing wrong?· I have to believe it is something simple about the timing or how I am doing the start-up call.· I don't need to add a %1 to the EEPROM_Addr to enable the write bit do I (for the R/W bit?)· ... I tried that and it didn't work either...
Thanks,
Steve
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Steve, N5AC
Comments
I don't see anything wrong with what you've posted.
You do have unnecessary WAITCNTs after the readLocation calls. You only need them after writes.
I've had problems sometimes with James' routines and the boot EEPROM setup. I don't know why. You might try the other I2C routines in the Object Exchange.
I have used Mike Greens "minimal_i2c_driver" without issue - it does exactly what it says on the tin !
Sample shown is for aux eeprom on different pins...(26,27)
Pub write(value)
' Write value to EEprom
·· outa[noparse][[/noparse]26] := 1 ' set SCL high
·· dira[noparse][[/noparse]26] := 1
·· dira[noparse][[/noparse]27] := 0 ' set SDA as input
·· Auxeeprom.i2cWritepage(26,$A0,$7FFC,@value,2)
·· waitcnt(clkfreq / 200 + cnt)
note: wait after write ...
Pub GetVal(Gval)
'Get stored value from Aux EEprom
·repeat 9
···· outa[noparse][[/noparse]26] := 0
···· outa[noparse][[/noparse]26] := 1
·Auxeeprom.i2cReadPage(26, $A0, $7FFC, @Gval, 2)
·setval := gval
The toggle(x9) at the start of the GetVal routine is something suggested by Mike on a forum post which counteracts spurious read error after a reboot.
Quattro
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
'Necessity is the mother of invention'
Post Edited (QuattroRS4) : 3/16/2007 5:58:50 PM GMT
Thanks,
Steve
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Steve, N5AC
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
'Necessity is the mother of invention'
Thanks
Write and Read (and Start and Stop) are low level I2C routines used by the ReadPage and WritePage and the WriteWait routines. They could be used to access some other kind of I2C device like an A/D converter or clock. Look at any I2C device datasheet for a description of the pieces that make up an I2C transaction.
I would really like to get a grasp on the concept Mike has here. It appears that the pointer for where the variable liaves in RAM is the same pointer used on the EEPROM to write to, but that doesn't make sense yet. What if the EEPROM was full with a program? Furthermore, what if I need to write beyond the 32k limit? I am thinking this isn't the best code example for what I am trying to do, which is store permanent user input on the EEPROM, that even if the EEPROM is reprogrammed, it stays. I have two EEPROMS on the board, so using the second EEPROM was actually the plan for storing permanent user input, but to learn I am trying to write over the single EEPROM on a Prop Stick.
The current plan is two have both EEPROMS on the same pins, with a few other I2C devices, both pins pulled up with 4.7k. I like the idea of writing and reading a variable to the EEPROMS, but if stricktly an address is required, that will work. Any suggestions on a good example or object to look at? Beans HITT version worked, but it is noted *not for general I2C stuff, and I want to use othe stuff on the pins.
Post Edited (originator) : 3/17/2007 11:14:06 AM GMT
This is all explained in the comments and the example calls in the Basic_I2C_Routines source.
I was stuck on the PCF8575 code, where I kept everything separate: device + address + R/W, data1, data2, stop. Here is the dumb part, I was thinking the chip address was the 3 pin chip select and the addrReg was the devicde ID!
Thanks
Post Edited (originator) : 3/17/2007 10:08:49 PM GMT
If you look at the source of the "Basic_I2C_Driver" object, you'll see the ReadPage and WritePage routines, then routines that use these to read and write a byte, a word, and a long. The latter routines are for convenience since they take the value to be written as a parameter or return the value read as the result of the call. Keep in mind that all the write routines do a paged write, so all affected EEPROM locations have to fit within a page. Reading is not an issue since the affected locations only have to be within the same 64K EEPROM. To do what Chip suggests and not have to worry about page boundaries, you have to write a byte at a time like:
The reason for supplying the address and value separately is in case you don't want to change the value until the next reboot.
If, say, you want to backup some long's value ... call it "x", you'd do: "saveLong(@x,x)". The saved value will be reloaded on the next reboot.
I am not clear from notes in Beans/Beaus EEPROM Write code thread, that F11 nukes the entire EEPROM, even data stored above the 256K mark on a 512?
***edit is there no way to view the EEPROM with F8? I tried to write a byte at EEPROM, $7000, Save EEPROM file, Open file, and nothing as at $7000
Post Edited (originator) : 3/17/2007 10:36:49 PM GMT