I2C slave reading and writing.

It would help greatly if the documentation for the Wire library stated explicitly what is going on with the Start, Stop, and Ack conditions on the bus. I'm trying to use an Arduino to emulate a device that uses 16 bit registers with 16 bit addresses. To read a register, The Master should send a START, the device address with R for bit 0, and a 16 bit address with no STOP at the end; it should then read two bytes, ACK after each then issuing a STOP condition .

  • How does the slave know that the STOP condition has been issued and that it can return to waiting for an address?
  • I note that the Wire.endTransmission() call has a stop parameter, but there's no indication as to when the STOP actually is sent.

Another, related question: When writing many bytes of data, the master will write the address, then continue writing data, receiving an ACK, until the master issues a STOP condition, which resets the state of the slave. Does Wire.onReceive() continue cycling until the STOP is received? Or does it enter repeatedly until the master issues the STOP condition?

How does the slave know that the STOP condition has been issued and that it can return to waiting for an address?

The Wire library doesn't support that. The Wire library should offer an easy to use interface to the I2C hardware in the Arduino world. It's not intended to support every rather weird device emulation. If you need that you're free to use the hardware directly.

I note that the Wire.endTransmission() call has a stop parameter, but there's no indication as to when the STOP actually is sent.

If the parameter is true (default) it's sent at the end of the transmission. It doesn't make any sense to send it somewhere in the middle of the transmission so that behavior is exactly what one would expect.

Does Wire.onReceive() continue cycling until the STOP is received?

It doesn't cycle. It's called whenever a stop or repeated start condition is detected (AVR platform). The data is kept in an internal buffer of the Wire library.

pblase42:
I'm trying to use an Arduino to emulate a device that uses 16 bit registers with 16 bit addresses.

Then ask the question that needs to be asked: "Can I use an Arduino to emulate a I2C device ?".
The answer is: "No".
To be more precise: 99% "No" and 1% "Maybe".

Have you searched this forum for emulating a I2C device and how everyone fails ?

The 16 bit registers with 16 bit register-address is no problem. The basic I2C communication is the problem.
When a Master requests data from an Arduino (the Arduino as I2C Slave) then the Arduino keeps the SCL line low while running the onRequest handler. That is called "clock pulse stretching" and the Master has to support that.
If the Master is an Arduino then it supports that.
If the Master is an other microcontroller running the I2C bus with software, then it might not support that and it might even have other timing and protocol issues that conflicts with the Arduino Wire library.

I hope you are not talking about a 16-bit I2C address. That is not according to the I2C standard.

What kind of device is it ? Do you know what microcontroller is used as a Master ? Is the I2C bus a 3.3V bus or a 5V bus ? Do you use a 3.3V Arduino board or a 5V arduino board ? Did you connect the GNDs ?

I'm a big fan of the 30 dollar LHT00SU1 logic analyzer together with the open source sigrok and PulseView. It can decode the I2C signals so you see the timing and also the data. Turn off the analog channel of the LHT00SU1 in PulseView to sample the digital signals at a higher rate. The cheaper 10 dollar 24MHz 8 channel logic analyzers also work, but their build quality is not good.

A quick look on the text of this post may help the OP to understand some of the important concepts of I2C Bus.