I've been trying to get a 24LC256 working with a 16F877A on a EasyPIC3 without much luck. As far as I can tell I have the wiring correct with pullups on SDA and SCL. I have chip address pins set correctly. I've tried different chips (sizes and make) with the same result. It always on the first write operation.
I tried a I2C and software I2C examples with equal lack of success (from the basic examples directories).
Is there something fundamental, which I may have missed, to getting these working? Is there an issue with the EasyPIC3 and external EEPROMs?
Thanks for any help.
Mark
I2C EEPROM Question
Take a look at the posts here. I believe that Rackley got it working in the end.
http://www.mikroe.com/forum/viewtopic.p ... ht=24lc256
http://www.mikroe.com/forum/viewtopic.p ... ht=24lc256
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]
[url=http://circuit-ed.com]CircuitED -[/url]
Please bear in mind this is MUCH more complicated than it should be due to bugs in hi() and lo() when dealing with byref variables and also bugs with compound statements. BUT, they work around the bugs and all the subs work.
Code: Select all
const EECtrlRead = %10100001 ' Control bytes to address the chip
const EECtrlWrite = %10100000
'------------------------------------------------------
' Reads a 20-char string from eeprom at Addr location.
' Modifies an array sent to it by reference as a return
'------------------------------------------------------
sub procedure I2C_ReadString(Dim Addr as Word, Dim ByRef Arr as String[20])
Dim i as byte
I2C_init(100000)
Delay_ms(10)
I2C_Start
I2C_Wr(EECtrlWrite) ' Issue write just to set the working address in EEPROM
I2C_Wr(hi(Addr))
I2C_Wr(lo(Addr))
I2C_Repeated_Start ' Terminate write and issue start of new operation
I2C_Wr(EECtrlRead) ' Issue read command
for i=0 to 18
Arr[i] = I2C_rd(1) ' Issue ACK so we get another byte
next i
Arr[19] = I2C_rd(0) ' Do not issue ACK since we're done reading and will send stop
I2C_Stop ' Send stop
end sub
'------------------------------------------------------
' Writes a 20-char string from eeprom at Addr location.
' Calling function must be sure not to write over a page boundry
'------------------------------------------------------
sub procedure I2C_WriteString(Dim Addr as Word, Dim ByRef Arr as String[20])
Dim i as byte
I2C_init(100000)
Delay_ms(10)
I2C_Start
I2C_Wr(EECtrlWrite) ' Issue write just to set the working address in EEPROM
I2C_Wr(hi(Addr))
I2C_Wr(lo(Addr))
for i=0 to 19
I2C_Wr(Arr[i])
next i
I2C_Stop ' Send stop
delay_ms(40)
end sub
'------------------------------------------------------
' Reads a byte from eeprom at Addr location.
' Returns a byte.
' Increments Addr by 64 automatically to advance to the next page
'------------------------------------------------------
sub function I2C_ReadByte(Dim ByRef Addr as word) as Byte
Dim tmpWord as Word
Dim tmpByte as Byte
Dim tmpByteStr as String[3]
I2C_init(100000)
Delay_ms(10)
I2C_Start
I2C_Wr(EECtrlWrite) ' Issue write just to set the working address in EEPROM
tmpWord = Addr ' Do some shuffling to get hi and lo without using functions
tmpWord = tmpWord >> 8
tmpByte = byte(tmpWord) ' Move high to low and clip off high to get our high
I2C_Wr(tmpByte)
tmpWord = Addr
tmpByte = byte(tmpWord) ' Clip off high to get our low
I2C_Wr(tmpByte)
I2C_Repeated_Start ' Terminate write and issue start of new operation
I2C_Wr(EECtrlRead) ' Issue read command
result = I2C_rd(0) ' Do not issue ACK since we're done reading and will send stop
I2C_Stop ' Send stop
Addr = Addr + 64
end sub
'------------------------------------------------------
' Reads a word from eeprom at Addr location.
' Returns a word.
' Increments Addr by 64 automatically.
'------------------------------------------------------
sub function I2C_ReadWord(Dim ByRef Addr as word) as Word
Dim tmpWord as Word
Dim tmpByte as Byte
I2C_init(100000)
Delay_ms(10)
I2C_Start
I2C_Wr(EECtrlWrite) ' Issue write just to set the working address in EEPROM
' Send address in byte chunks
tmpWord = Addr ' Do some shuffling to get hi and lo without using functions
tmpWord = tmpWord >> 8
tmpByte = tmpWord ' Move high to low and clip off high to get our high
I2C_Wr(tmpByte)
tmpWord = Addr
tmpByte = tmpWord ' Clip off high to get our low
I2C_Wr(tmpByte)
I2C_Repeated_Start ' Terminate write and issue start of new operation
I2C_Wr(EECtrlRead) ' Issue read command
tmpWord = I2C_rd(1)
tmpWord = tmpWord << 8
tmpWord = tmpWord + I2C_rd(0)
result = tmpWord
'result = word(I2C_rd(1) << 8) ' Issue ACK so we get another byte, shift first byte to upper byte
'result = result + I2C_rd(0) ' Do not issue ACK since we're done reading and will send stop and
' add lower byte with AND operation
I2C_Stop ' Send stop
Addr = Addr + 64
end sub
'------------------------------------------------------
' Writes a byte to eeprom at Addr location.
' Returns nothing.
' Increments Addr by 64 automatically.
'------------------------------------------------------
sub procedure I2C_WriteByte(Dim ByRef Addr as word, Dim Data as Byte)
Dim tmpWord as Word
Dim tmpByte as Byte
I2C_init(100000)
Delay_ms(10)
I2C_Start
I2C_Wr(EECtrlWrite) ' Issue write just to set the working address in EEPROM
' Send address in byte chunks
tmpWord = Addr ' Do some shuffling to get hi and lo without using functions
tmpWord = tmpWord >> 8
tmpByte = byte(tmpWord) ' Move high to low and clip off high to get our high
I2C_Wr(tmpByte)
tmpWord = Addr
tmpByte = byte(tmpWord) ' Clip off high to get our low
I2C_Wr(tmpByte)
I2C_Wr(Data)
I2C_Stop ' Send stop
delay_ms(10)
Addr = Addr + 64
end sub
'------------------------------------------------------
' Writes a word to eeprom at Addr location.
' Returns nothing.
' Increments Addr by 64 automatically.
'------------------------------------------------------
sub procedure I2C_WriteWord(Dim ByRef Addr as word, Dim Data as Word)
Dim tmpWord as Word
Dim tmpByte as Byte
I2C_init(100000)
Delay_ms(10)
I2C_Start
I2C_Wr(EECtrlWrite) ' Issue write just to set the working address in EEPROM
' Send address in byte chunks
tmpWord = Addr ' Do some shuffling to get hi and lo without using functions
tmpWord = tmpWord >> 8
tmpByte = tmpWord ' Move high to low and clip off high to get our high
I2C_Wr(tmpByte)
tmpWord = Addr
tmpByte = tmpWord ' Clip off high to get our low
I2C_Wr(tmpByte)
' Send data in byte chunks
tmpWord = Data ' Do some shuffling to get hi and lo without using functions
tmpWord = tmpWord >> 8
tmpByte = tmpWord ' Move high to low and clip off high to get our high
I2C_Wr(tmpByte)
tmpWord = Data
tmpByte = tmpWord ' Clip off high to get our low
I2C_Wr(tmpByte)
I2C_Stop ' Send stop
delay_ms(40)
Addr = Addr + 64
end sub
Well I've sort of made some progress with this although I've discovered something which confuses me even more! Wouldn't take much actually
I can get it to half work if I cycle the power - it does a write but fails on a read. If I just do a reset (or after programming) it hangs on the first write (according the leds)?
What's even more confusing though is if I put a delay, before any code at the start, it doesn't work at all!? Also, putting extra delay elsewhere (not between a start and stop) gives different results.
Is there an issue with the EasyPIC3? Or is this a devlish timing problem?
I saw another example for I2C and EEPROMs which I might have a look at. Unfortunately it's written in assembler so it isn't going to be easy to quickly throw in a few routines. It would be interesting to find out at a low level where the problem is though.
I can get it to half work if I cycle the power - it does a write but fails on a read. If I just do a reset (or after programming) it hangs on the first write (according the leds)?
What's even more confusing though is if I put a delay, before any code at the start, it doesn't work at all!? Also, putting extra delay elsewhere (not between a start and stop) gives different results.
Is there an issue with the EasyPIC3? Or is this a devlish timing problem?
I saw another example for I2C and EEPROMs which I might have a look at. Unfortunately it's written in assembler so it isn't going to be easy to quickly throw in a few routines. It would be interesting to find out at a low level where the problem is though.
I can't really speculate, but I had problems with I2C as well. Specifically, I have to reinitialize the I2C bus for every function, even though I follow the datasheet specifications for I2C communications exactly. There is something going on with the I2C communications that isn't right that made me need to reinit for each function, and it seems to be something in the closing or starting of the communication (for me at least.)sparkz wrote:Well I've sort of made some progress with this although I've discovered something which confuses me even more! Wouldn't take much actually
I can get it to half work if I cycle the power - it does a write but fails on a read. If I just do a reset (or after programming) it hangs on the first write (according the leds)?
What's even more confusing though is if I put a delay, before any code at the start, it doesn't work at all!? Also, putting extra delay elsewhere (not between a start and stop) gives different results.
Is there an issue with the EasyPIC3? Or is this a devlish timing problem?
I saw another example for I2C and EEPROMs which I might have a look at. Unfortunately it's written in assembler so it isn't going to be easy to quickly throw in a few routines. It would be interesting to find out at a low level where the problem is though.
Hmm, I've been playing around with another compiler (sorry not mE!). I managed to get it working fine there. Standard out of the book stuff - no special timings or adjustments needed. Which is a relief. Glad to know I hadn't messed up and the EasyPIC and other hardware is ok.
Wonder why the mB routines are so temporamental? Is it just down to certain suspect code generation or is there an issue with the core routines?
Wonder why the mB routines are so temporamental? Is it just down to certain suspect code generation or is there an issue with the core routines?
Following works for me on the IC2:
ConFigHi = I2C_Rd(Acknowledge)
IC2PauseOnBusy
ConFigLo = I2C_Rd(DontAcknowledge)
Where IC2PauseOnBusy is following routine
Sub procedure IC2PauseOnBusy
' ---------------------------------------------------------
' Pause until I2C bus is avaliable
' used on writes to bus only
' ---------------------------------------------------------
while I2C_Is_Idle = FALSE
nop
wend
end sub
dab
ConFigHi = I2C_Rd(Acknowledge)
IC2PauseOnBusy
ConFigLo = I2C_Rd(DontAcknowledge)
Where IC2PauseOnBusy is following routine
Sub procedure IC2PauseOnBusy
' ---------------------------------------------------------
' Pause until I2C bus is avaliable
' used on writes to bus only
' ---------------------------------------------------------
while I2C_Is_Idle = FALSE
nop
wend
end sub
dab
I don't know where the problem lies (which makes me very hesitant to use other I2C technologies with mikroBasic), but just like your experience, I have never had any problems whatsoever in other compilers.sparkz wrote:Hmm, I've been playing around with another compiler (sorry not mE!). I managed to get it working fine there. Standard out of the book stuff - no special timings or adjustments needed. Which is a relief. Glad to know I hadn't messed up and the EasyPIC and other hardware is ok.
Wonder why the mB routines are so temporamental? Is it just down to certain suspect code generation or is there an issue with the core routines?
Yes there should be bug.rackley wrote: I can't really speculate, but I had problems with I2C as well. Specifically, I have to reinitialize the I2C bus for every function, even though I follow the datasheet specifications for I2C communications exactly. There is something going on with the I2C communications that isn't right that made me need to reinit for each function, and it seems to be something in the closing or starting of the communication (for me at least.)
I tried this 2 weeks ago and i2c library did not function as it should do.
You have to init i2c very time.
and you should add delay between all commands.
I think mE should consider revising i2c library..
Make sure you check to see that the i2c bus is free before using, I've used it on different chips and found it to work on all OkYes there should be bug.
I tried this 2 weeks ago and i2c library did not function as it should do.
You have to init i2c very time.
and you should add delay between all commands.
I think mE should consider revising i2c library..
dab