I2C Repeated Start Issue


#1

My problem is that the Wire.h library seems to resend the address after Wire.endTransmission(false).

I am attempting to write to a sensor’s configuration register. The process requires a repeated start as shown from the sensor’s datasheet.

My initial attempt used the following sequence of commands:

On the wire this results in an:
address(0x48),
command(0xAC),
a resend of the address(0x48),
and the data(0x05).

0x05 is the value I need to send to the register. This needs to occur directly after the 0xAC + ACK. But as seen, the address is resent.

In my second attempt I did not call beginTransmission():

However, this still resends the address as seen on the wire:

I tried parsing through Wire.cpp, but my fix attempts only resulted in breaking the I2C engine.

Might I have something wrong?
I can’t imagine any other sequence of Wire calls to generate the repeated start I need.

Thanks


#2

@david-kooi

First of all, let me compliment you on your choice of logic analyzer :wink: I’ve used a Saleae Logic for a long time now. Love it.

From the timing diagram you posted, it looks like you don’t need a repeat start.

Wire.beginTransmission(TS_DEVICE_ADDRESS);
Wire.write(TS_CONFIG_REG);
Wire.write(TS_CONFIG_REG_STARTUP);
Wire.endTransmission();  

That should be all you need.

A repeat start is usually used to do a write of a command (say to set the register location), and then to do a read of that register without releasing the bus in between the read and write (Where CAPS are master, lower is from slave).

(START+ADDR+W)(REG)(START+ADDR+R)(value)(STOP)

As opposed to:

(START+ADDR+W)(REG)(STOP)(_)(START+ADDR+R)(value)(STOP)

On your Logic capture, the Green dot is the start bit, the Red dot is the stop. So it is sending a repeat start, and yes that does include the address byte also.

For multi-byte writes:

(START+ADDR+W)(REG)(DATA0)(DATA1)…(DATAN)(STOP)

The only practical use of the repeat start is that it prevents another master from taking the bus in between the write and the read (the _ ). If you aren’t using a multi-master I2C bus, it doesn’t really matter. That being said, repeat starts are ‘standard’ for that scenario (as standard as anything gets with I2C anyway) and some slave ICs require a repeat start for a write-read sequence because they do an internal reset on a stop bit.

If you look at the driver for the Fuel Gauge, you can see an example. quickStart() does a register write and 2 value writes. percentage() does a register write, and then a 2 value read, utilizing a repeat start.


#3

That was it.

Thanks for the overview. Hopefully it’ll help another person down the line.
:slight_smile: