I found ONE of the problems. One of them is indeed a problem with passing the eeprom address word via ByRef. If I pass it ByRef the subroutine sometimes returns the eeprom address instead of the variable "result."
Bear with me because this is pretty crazy. Bear in mind the actual return value SHOULD be "68" decimal.
This code does not work, as I need to reinitialize the I2C bus every time I read from it or it returns "139" decimal once, then returns "160" decimal every subsequent read attempt:
Code: Select all
sub function I2C_ReadByte(Dim Addr as word) as Byte
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
result = I2C_rd(0) ' Do not issue ACK since we're done reading and will send stop
I2C_Stop ' Send stop
end sub
This returns "Addr" as the return value for the sub instead of the byte "result". Addr is "151" decimal. If I throw in the "Addr = Addr + 64" at the end of the sub it will return "139" or "145" or somewhere in that range every time regardless of what Addr is (I can vary it via an ADC input but it's normally constant.) But even if I vary Addr the result stays constant, when it should be refreshing (and therefore changing) every two seconds.
Code: Select all
sub function I2C_ReadByte(Dim ByRef Addr as word) 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
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
This is the ONLY way it will function correctly:
Code: Select all
sub function I2C_ReadByte(Dim Addr as word) 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
result = I2C_rd(0) ' Do not issue ACK since we're done reading and will send stop
I2C_Stop ' Send stop
end sub
This version also refreshes and varies the return value, as it should, every two seconds. The return value is not "fixed" for the whole runtime of the PIC until it is reset.
I stumbled on the only working version of my sub by pure trial and error. None of the incorrect results I'm getting back in the other versions make any sense whatsoever, which is why I was so stumped and frustrated. Z, I think you might want to try these out and see if you can reproduce these problems, because technically ANY of these versions of the sub should work 100%, but only the last one really works.
I can send you my whole program if you'd like (which isn't very much since I've been stuck on this) but varying ONLY the read byte sub is what seems to break/fix it.
Let me know if that post made any sense at all