This is a follow-up question to What happens if I omit the pullup resistors on I2C lines?

In a digital wall clock I designed (using the DS1307 RTC and the ATmega328 MCU), I accidentally omitted the pull-up resistors that must be wired to both I2C lines. In the end I was lucky enough that the internal pull-ups on the ATmega I2C lines were enough to (barely) allow the communication between the devices. The result were long rise times on the I2C lines and speed reduction to 32kHz as seen in the scope shots below.

Edit: Actually, the frequency is exactly 100kHz - there are 2 peaks per 20us on the green trace. I initially thought there was a reduction to 32kHz because my scope calculated the frequency on the yellow trace.

Scope shot 1 Scope shot 2

What's puzzling me now is how the devices decided that 32kHz was enough for the communication to take place. The DS1307 datasheet says that the device supports 100kHz frequency on the I2C bus. How come it ended up using 32kHz instead? Is there some kind of handshake phase where the frequency is stablished?

In the end, my question really is this: How is the clock frequency established between master and slave in I2C protocol?

I couldn't find that information searching the Net.

In case this matters, I'm using Arduino IDE 1.03 and my firmware handles the RTC using the DS1307RTC Arduino lib (through its functions RTC.read() and RTC.write()). That lib in turn uses Wire.h to talk to the RTC.

  • 4
    \$\begingroup\$ The standard for I2C is here \$\endgroup\$ Mar 13, 2014 at 13:46
  • 1
    \$\begingroup\$ Couldn't this be you arbitrarily hard-coding that frequency without knowing it? \$\endgroup\$
    – Dzarda
    Mar 13, 2014 at 13:51
  • \$\begingroup\$ @Warren That reference is really helpful, thanks. I couldn't get Google to take me to THE SPEC. Instead, it took me to Wikipedia article and other tangencial docs. Still, I couldn't understand how speed is determined. I think what I want to know is in section 3.1.7 Clock synchronization, but I would really appreciate if someone could explain that to me in simpler terms, as it is still a bit over my head. \$\endgroup\$
    – Ricardo
    Mar 13, 2014 at 13:55
  • 1
    \$\begingroup\$ In your system the DS1307 is a slave and it's SCL line is an input only. The frequency is set by the master the MCU. Whoever wrote the firmware for it decided what speed they wanted. There is no negotiation its hard coded. \$\endgroup\$ Mar 13, 2014 at 14:04
  • 1
    \$\begingroup\$ Correct most systems have only one master, clock sync only makes sense in a multi-master environment \$\endgroup\$ Mar 13, 2014 at 14:17

3 Answers 3


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

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)

  • 1
    \$\begingroup\$ "If you want to change it, I'd suggest #undef and #define on TWI_FREQ after you include Wire.h" No, that's incorrect. The way twi.h is written, you should #define your custom TWI_FREQ before you #include twi.h. (And what does "Wire.h" have to do with anything?) \$\endgroup\$
    – Dave Tweed
    Mar 13, 2014 at 16:07
  • \$\begingroup\$ Actually, the frequency has always been exactly 100kHz - there are 2 peaks per 20us on the green trace. I initially thought there was a reduction to 32kHz because my scope calculated the frequency on the yellow trace. This makes your answer correct. Thanks!! \$\endgroup\$
    – Ricardo
    Oct 12, 2014 at 1:05

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.


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


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.