Forum Index
HomeZBasic Home   Forum RulesForum Rules   Forum FAQForum FAQ   MemberlistMemberlist   UsergroupsUsergroups   RSS FeedRSS Feed
Site SearchSite Search   LinksLinks   DownloadDownload   Digests and SubscriptionsDigests and Subscriptions
ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in   RegisterRegister
How to do I2C with two items

 
Post new topic   Reply to topic    Forum Index -> General
Author Message
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 24 June 2010, 11:05 AM    Post subject: How to do I2C with two items Reply with quote

I have two I2c devices, PCF8574 I/O expanders attached to a ZX-24. One has a slave address of &H000 and the other &H001. I wish to read one then read to other, wait a bit and then read them again in a loop. How do I structure the I2c cycle code-wise. I am using the hardware I2C bus.

I.m not looking for code but rather code structure.

Any enlightenment will be appreciated.

Vic
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR

Posted: 24 June 2010, 15:29 PM    Post subject: Re: How to do I2C with two items Reply with quote

victorf wrote:
One has a slave address of &H000 and the other &H001.
Just to be clear, those are the sub-addresses. The base address of a PCF8574 is &H40 (in contrast to PCF8474A having a base address of &H70). This means that the 8-bit I2C address of one device will be &H40 and the other will be &H41.

victorf wrote:
I wish to read one then read to other, wait a bit and then read them again in a loop.
You simply execute the I2CCmd() function for one and then again for the other. For example:
Code:
Const i2cChan as Byte = 0
Const i2cAddr1 as Byte = &H40
Const i2cAddr2 as Byte = &H41
Do
  stat = I2CCmd(i2cChan, i2cAddr1, 1, dataOut1, 1, dataIn1)
  stat = I2CCmd(i2cChan, i2cAddr2, 1, dataOut2, 1, dataIn2)
Loop
The example code above assumes that you need to output data to and input data from both devices each time. If you only need to read data or only write data you can set the third and fourth or fifth and sixth parameters, respectively, to zero.
Back to top
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 25 June 2010, 12:44 PM    Post subject: Reply with quote

Don,

Thanks for the quick reply and for clearing up the sub-address issue.

Before starting the DO-LOOP in your example, I assume that I need to call
OpenI2C() and then when I break out of the loop ( I have a While (condition)/Wend type), I should call I2CStop().

Vic
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR

Posted: 25 June 2010, 15:17 PM    Post subject: Reply with quote

victorf wrote:
I assume that I need to call OpenI2C() and then when I break out of the loop ( I have a While (condition)/Wend type), I should call I2CStop().
Normally, you would call OpenI2C() once in your application and never call CloseI2C(). There is no advantage to be gained by repeatedly opening/closing the I2C channel.

Once the channel is open, you can use it to perform as many I2C transactions with as many slave devices as you like. Each I2C transaction is implemented either by invoking I2CCmd() or by a specific sequence of I2CStart(), I2CPutByte(), I2CStart() (yes, again), I2CGetByte() and I2CStop() calls. These two methods of creating the I2C transaction are called the high-level and low-level methods, respectively. The low-level method requires more understanding of the particulars of the the I2C protocol but has the advantage of permitting some of the data values to be computed during the sequence generation. With the high-level method, all data values must be known before calling I2CCmd().

As described in a recent thread related to an SMBus device, a low-level transaction has one of two possible forms - one with just a write phase and one with both a write phase and a read phase. Which form to use depends on the slave device and its requirements. A low-level generated transaction containing just a write phase would look something like this:
Code:
' this is the write-phase
Call I2CStart(chan)  ' this generates a "start condition"
stat = I2CPutByte(chan, slaveAddr And &Hfe) ' LSB must be zero
stat = I2CPutByte(chan, cmd)
<call I2CPutByte() to send other command/data bytes as necessary>
Call I2CStop(chan)  ' this generates a "stop condition

A low-level transaction with both phases would look something like this:
Code:
' this is the write-phase
Call I2CStart(chan)   ' this generates a "start condition"
stat = I2CPutByte(chan, slaveAddr And &Hfe) ' LSB must be zero
stat = I2CPutByte(chan, cmd)
<call I2CPutByte() to send other command/data bytes as necessary>

' this is the read phase
Call I2CStart(chan)  ' this generates a "repeated start condition"
stat = I2CPutByte(chan, slaveAddr Or &H01) ' LSB must be one
ReadByte(1) = I2CGetByte(chan, True)   ' ACK on all but the last byte
<read additional data bytes as necessary using I2CGetByte()>
ReadByte(N) = I2CGetByte(chan, False)  ' NAK on last byte
Call I2CStop(chan)   ' this generates a "stop condition
Note, particularly, that if there is only one byte to be read in the read phase, the second parameter in the one and only call to I2CGetByte() would be False. If there are multiple calls to I2CGetByte(), the second parameter must be True on all but the last.

As you might guess, the high-level I2CCmd() does nothing more than implement the sequences described above depending on the number of bytes to be written and the number of bytes to be read. Note, also, that it is possible for an I2C transaction to consist of just a read phase but the write and write/read transactions are more common.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    Forum Index -> General Time synchro. with the server - Timezone/DST with your computer
Page 1 of 1

 


All content Copyright © 2005-2012 Elba Corp. All Rights Reserved.
Opinions expressed in posts are those of the author and not necessarily those of Elba Corp.
Powered by phpBB © 2001, 2005 phpBB Group