How is the clock frequency established between master and slave in I2C protocol?

For a rising clock edge occur in I2C, the master must assert the clock, which may cause some slaves to join in asserting it as well, and then the master and all slaves must concur in releasing the clock. Until all devices release the clock, it will remain asserted and all devices will see that it's asserted.

Once every device has released the clock, then each slave device will "re-arm" the clock-hold circuit unless or until it will be ready for the next rising edge [some devices are always "ready" for rising edges as fast as the master can send them, and thus don't need a clock-hold circuit at all; others may sometimes know they won't be interested in any rising edges until the next start condition appears, and not re-arm their clock-hold circuit until then]. When the master sees that the clock is released, it waiting some minimum length of time to ensure that anyone who needs to re-arm a bus-hold circuit has a chance to do so, and then re-assert the clock and ensure that it's held long enough to allow any armed bus-hold circuits to join in holding it. The cycle can then repeat.

Slave devices generally do not have a minimum speed of operation, but will have a maximum. Some devices synchronize all their I2C logic to an internal clock, and may thus require a cycle or two to arm or trigger their clock-hold circuit. Additionally, I2C requires that devices must 100% reliably determine whether edges on the clock wire happen before or after edges on the data wire; since data line changes often occur almost immediately after falling clock edges, devices may add some delay in when they perceive data-line changes. This requires adding a delay between any time the master changes its data output and the time it raises its clock. Provided every device has its minimum delay requirement satisfied, the master can delay as long as it wants; the longer the master delays, though, the longer it will take to send data.


Following up the comments:

Yes, the frequency is hard-coded into some specific I2C-related registers. At runtime.

That said, your Arduino library might be doing some probing and rise time measurement on the bus for determining a viable clock rate. Let's see.


After doing a bit of source-digging, the answer is in twi.h

#ifndef TWI_FREQ
#define TWI_FREQ 100000L
#endif

Another piece from that very file:

TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2;

Where TWBR stands for Two Wire Baudrate Register I suspect.

I'd call that enough evidence and definitely say, yes your I2C frequency is set directly by your library without any negotiations. If you want to change it, I'd suggest you #define TWI_FREQ before you #include twi.h (or indirectly through Wire.h)


From The Arduino website- Wire Library Detailed Reference:

The twi.init() call is internal to the Wire library. It performs the following tasks: sets the clock frequency that the TWI hardware will use if/when it is the master on the I2C bus. It is set in the source code to 100kHz, but theoretically at least you can reset this frequency by redefining TWBR prior to calling Wire.begin(), eg: TWBR=400000L should set it to 400kHz.

The RTC library you use doesn't change TWBR. Something else you are using might have changed it. Or the long slow pull-up time from the super weak internal pull-ups have effectively caused the ATMega's i2c engine to slow down. The engine does check to see if the line is high or low before changing it.

That said, i2c clock frequency is arbitrary, up to the lowest maximum supported frequency of any device on the the bus (and maybe a few tens of Hz more). Any faster and you start getting read and write issues. Some devices have minimum frequencies before they time out, but I've seen 400khz devices work at 10khz. The clock speed is solely decided by the master (i.e. you, the coder).

There is an option for clock stretching on the slave's part (it holds the clock line low until it's ready, and the i2c spec requires that the master check for this), but the scope pictures don't seem to indicate that this is happening here.

If you were to add some proper external pullups, without changing any code, you should see the frequency increase closer to 100kHz as the Wire Library defines as standard

Tags:

I2C