i2c random access reads?
Chicago Mike
Posts: 88
I'm using i2c to read from a RTC clock, but I'm having a really interesting issue. I am reading from the same memory address TWICE in·different methods for various reasons, but I'm getting different results? No alteration of this address is occuring (As they are flag bits I'm trying to read). On the first read of this address (See Runonce) I get a result of say %01000101, but reseting the address pointer and reading again (See Runagain), I'm getting %00000010. Clearly there is something I'm missing here in regards to random access reading of i2c devices. Below I've commented the Run once, with what I believe each statements is doing (These methods were taken from James Burrows i2cobject). This was modified from the RTC1307 object to work with a different, but very similar RTC. A lot of code has been removed, (I'm using·i2object, and the lcd4x20 objects)> I did include the methods I am using to print·the bin to the LCD for testing.·I just can't figure why I would get a different response. Its got to have to do with my addressing?
--Mainline Program--
posbin(3,1,Runonce,8)
waitcnt(100_000_000+cnt)
posbin(3,10,Runagain,8)
--- methods---
PUB Runonce : htalarmRecord
· if started == true
··· i2cObject.i2cStart
··· ' Address the device
··· i2cObject.i2cWrite (rtc_Address | 0,8)
··· ' Set the memory pointer to $01 - The register I want to read
··· i2cObject.i2cwrite($01,8)
····i2cObject.i2cStart
··· ' Set the read flag
··· i2cObject.i2cWrite (rtc_Address | 1,8)
··· ' Read the register
··· htalarmRecord := i2cObject.i2cRead(i2cObject#_i2cACK)
··· i2cObject.i2cStop
' Exactly the same as above, but gives a different result
PUB Runagain : htstatus
· if started == true
··· i2cObject.i2cStart
··· i2cObject.i2cWrite (rtc_Address | 0,8)
··· i2cObject.i2cwrite($01,8)
··· i2cObject.i2cStart
··· i2cObject.i2cWrite (rtc_Address | 1,8)
··· htstatus := i2cObject.i2cRead(i2cObject#_i2cACK)
··· i2cObject.i2cStop
PUB posbin(line, column, value, digits)
· pos(line,column)
· bin(value,digits)
PUB bin (value, digits)
· VALUE <<= 32 - DIGITS
· REPEAT DIGITS
··· writeout((VALUE <-= 1) & 1 + "0")
--Mainline Program--
posbin(3,1,Runonce,8)
waitcnt(100_000_000+cnt)
posbin(3,10,Runagain,8)
--- methods---
PUB Runonce : htalarmRecord
· if started == true
··· i2cObject.i2cStart
··· ' Address the device
··· i2cObject.i2cWrite (rtc_Address | 0,8)
··· ' Set the memory pointer to $01 - The register I want to read
··· i2cObject.i2cwrite($01,8)
····i2cObject.i2cStart
··· ' Set the read flag
··· i2cObject.i2cWrite (rtc_Address | 1,8)
··· ' Read the register
··· htalarmRecord := i2cObject.i2cRead(i2cObject#_i2cACK)
··· i2cObject.i2cStop
' Exactly the same as above, but gives a different result
PUB Runagain : htstatus
· if started == true
··· i2cObject.i2cStart
··· i2cObject.i2cWrite (rtc_Address | 0,8)
··· i2cObject.i2cwrite($01,8)
··· i2cObject.i2cStart
··· i2cObject.i2cWrite (rtc_Address | 1,8)
··· htstatus := i2cObject.i2cRead(i2cObject#_i2cACK)
··· i2cObject.i2cStop
PUB posbin(line, column, value, digits)
· pos(line,column)
· bin(value,digits)
PUB bin (value, digits)
· VALUE <<= 32 - DIGITS
· REPEAT DIGITS
··· writeout((VALUE <-= 1) & 1 + "0")
Comments
ie..
waitcnt(400_000+cnt)
James
The only thing I can think of is that there's something going on in the device itself that changes the flags that are read. Without
a datasheet for the device, it's impossible to tell. These devices are RAM based usually and a delay between reads should not be
necessary.
Javalin,
His write cycle is part of the I2C read process.
You have to use write mode to supply a register address to the device before you can read the register.
I'm also planning on trying out an I2C RTC (maybe today?)...
Anyway, I'm going to use this stripped down version of Mike Green's I2C code that I previously used for I/O expansion over I2C:
http://www.rayslogic.com/propeller/Programming/i2c/PCF8574_Demo.zip
It was for systems like PC to hold config data
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nothing is impossible, there are only different degrees of difficulty.
Sapieha
After playing around a little more I have realized that regardless of what the second read does it comes back as wrong every time, however on the first call, regardless of the address, the data is correct. I've looked for an offset or something and I can't seem to find a pattern, leaving me with the belief its something in the code above.
Still looking.
Interesting - sorry didn't really read your first post - hence the EEPROM based response.
Attached is the beta of my device-objects using Mike Greens "basic_i2c_object" - plus a few bits.· Its not finished but maybe will help?
Given up on my i2cObject - too messy.
James
Oddly enough with this M41T812S I can do sequential reads without a problem, its just random access reads that seem to be the issue, which the datasheet claims it can do (like most other RTCs I've seen). I have never had this problem with any other i2c devices I've used. Then again all of my experience has been with eeprom or fram i2c devices. Tomorrow I'm going to try another of these M41T812S's to see if thats the problem (Pain because its a SOIC device on a breakout), then I may just order a different RTC that supports I2c to see if its really just this model I'm having problems with, or if its me.
Anyone has any suggestions for another I2c capable RTC, that has a SOIC form factor available, and had alarm features? (I"m asking a lot, I know, as this was the perfect device for me, and at around $.95, you can't go wrong).
Thanks,
Mike.
htalarmRecord := i2cObject.i2cRead(i2cObject#_i2cACK) which sent sent an ACK (LOW state). I changed it to
htalarmRecord := i2cObject.i2cRead(1). I'm going to switch my code over to Javalin's new RTC object which use Mike Greens BASIC-i2c_Object tonight for consistency. I noticed that the new RTC objects using BASIC_I2C_Object, reference i2cObject.i2cRead(i2cObject#_i2cNAK) on the final read, which would properly leave the ACK at 1, eliminating this problem.
Was in my face the entire time on the datasheet, but it took the v2 objects to notice it. Thanks for all the help!
J
Generally an RTC has a either a battery backup or a supercap backup (so that time/date and scratch RAM are maintained even when the main system is powered down). Depending on your application it can be cosmically useful to have RAM registers that are stable even after power-off.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST