repeat 8 dira[scl] := 0 i2cbyte := (i2cbyte << 1) | ina[sda] dira[scl] := 1 dira[sda] := !ackbit dira[scl] := 0 dira[scl] := 1 return (i2cbyte & $FF)
; FIGURE 4. EE write byte diagram.
We start by writing 0 to the dira bit for SDA which
puts it into input mode. A repeat loop takes the SCL line
high, shifts i2cbyte left one bit, then copies the state of
the SDA line to bit0 of i2cbyte. After the SCL sampling,
the SCL line is taken back low.
; FIGURE 5. EE read
byte diagram.
Earlier, I mentioned that the receiving end of the
transaction provides an ACK/NAK bit back to the sender
pub stop dira[sda] := 1 dira[scl] := 0 repeat until (ina[scl] == 1) dira[sda] := 0
pub wr_byte(ctrl, address, value) i2c.start i2c.write(ctrl & $FE) i2c.write(address.byte[1]) i2c.write(address.byte[0]) i2c.write(value) i2c.stop
— this is passed as a parameter to the read() method.
You'll need to check the datasheet for the component for
ACK/NAK bit usage.
In general, I've found that the receiver will provide a
ACK after all but the last byte read. We'll see this
shortly.
Finally, the stop() method terminates a transaction:
Pretty simple, right? Note that we're AND-ing the
control byte with $FE to make sure that bit0 is clear; this
is for write mode.
Memory Like an Elephant
An EEPROM never forgets, and as we have one
attached to every stand-alone Propeller project, we're
going to use it as an I2C training ground. If you don't
have it, go download the datasheet for the 24LC256 or
Before I continue, let me point something out to
those of you coming from the Arduino world, and to
those that may want to port useful Arduino projects to
the Propeller. The TWI (two-wire interface) library in the
Arduino treats addresses differently that we're doing
here. For example, if you look up Arduino code for an
EEPROM, you'll see that the control byte for an EEPROM
at address %000 is $50, not $A0 as we're using. The
reason is that the TWI library takes the address provided
and shifts it left by one bit to make room for the
Read/Write bit in the control byte.
24LC512 EEPROM (based on your board). You really
want to have this handy.
Let's start by writing a single byte to the boot
In my experience, most device vendors provide the
control byte value as we're using here (not right-shifted),
but you'll want to double-check that if you have problems
connecting to a device. The transaction diagrams usually
provide the clearest information vis-à-vis control byte.
EEPROM. We'll need to do the following:
• Start condition
Okay, let's read a byte back from the EEPROM. Since
the EEPROM maintains an address pointer, the process
can be this simple:
• Write control byte ($A0)
• Write high byte of address
• Start condition
• Write low byte of address
• Write control byte ($A1)
• Write data byte
• Read data byte
• Stop condition
• Stop condition
In Figure 4, you'll see a diagram that illustrates the
transaction — this is what you'll find in most I2C
component datasheets.
The transaction diagram for a simple byte read is
shown in Figure 5. Here's the translation to Spin:
Using the jm_i2c.spin object, we could add a
method to our program like this:
pub rd_byte | value i2c.start
May 2014 63