Take the 2-minute tour ×
Electrical Engineering Stack Exchange is a question and answer site for electronics and electrical engineering professionals, students, and enthusiasts. It's 100% free, no registration required.

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.

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.

share|improve this question
4  
The standard for I2C is here –  Warren Hill Mar 13 at 13:46
    
Couldn't this be you arbitrarily hard-coding that frequency without knowing it? –  Dzarda Mar 13 at 13:51
    
@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. –  Ricardo Mar 13 at 13:55
1  
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. –  Warren Hill Mar 13 at 14:04
1  
Correct most systems have only one master, clock sync only makes sense in a multi-master environment –  Warren Hill Mar 13 at 14:17

3 Answers 3

up vote 4 down vote accepted

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.

share|improve this answer

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)

share|improve this answer
1  
"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?) –  Dave Tweed Mar 13 at 16:07
    
Good point, thanks –  Dzarda Mar 13 at 16:14

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

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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