cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Fast Mode 400KHz

hazelnusse
Associate III
Posted on July 11, 2011 at 21:13

I'd like to use a Connectivity Line STM32's (STM32F107) I2C peripheral in the 400Khz fast mode. I'm using a Olimex STM32-H107, which has a 25MHz external crystal. I am confused by what the reference manual says (RM0008) in the section about the I2C_CCR:

Quote:

To use the I2C at 400 KHz (in fast mode), the PCLK1 frequency (I2C peripheral input clock) must be a multiple of 10 MHz.

At first glance, this seems to imply that my system clock will have to be something like 60Mhz so that the peripheral clock could be 30Mhz.

Is there a way to use a 25Mhz external crystal and keep the system clock at 72Mhz (it's maximum), and yet still get the peripheral clock to be a multiple of 10Mhz so that I can use fast mode?

It would be ironic if in order to use I2C fast mode, I would have to slow down my system clock from 72Mhz to 60Mhz, so it seems like there must be a way to configure the clocks that allow both a 72Mhz system clock as well as the ability to use the fast mode.

#i2c-stm32-stm32f107
7 REPLIES 7
Posted on July 11, 2011 at 23:53

One of the ''notes'' is kind of floating in an odd place in the document, I think it should be tied to the DUTY bit. In 16/9 (div 25) duty, you're going to want a 10 MHz basis for that to work at ideal frequencies. ie you'd be working at 320 KHz with 8 MHz multiples.

CR2 is programmed with the MHz speed of the PCLK, I think this is for timeouts/rise times, as the shift clock is handled by CCR

In fast=1,duty=0 the clock needs to be a multiple of 1.2 MHz to achieve a 66/33% duty I2C clock, In fast=1,duty=1 the clock needs to be a multiple of 10 MHz to achieve 64/36% duty I2C clock.

60 * 1.2 = 72 MHz, you have a winner

Fast mode should be viable at rates up to 400 KHz, it can be under 400 KHz and work, it is not required to be AT 400 KHz.

Now, it wouldn't surprise me if you could use fast=0 to get rates exceeding 100KHz with 50/50% duty cycles.

You'll want to experiment.

So in summary

fast=0, uses a div 2 clock generator, with a 50/50% duty

fast=1, duty=1, uses a div 25 clock generator, with a 64/36% duty

fast=1, duty=0, uses a div 3 clock generator, with a 66/33% duty
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 12, 2011 at 00:15

Peripheral clock = 36MHz

CCR    fst=0        fst=1,dty=0  fst=1,dty=1

004 :  4500000.000  3000000.000   360000.000

01E :   600000.000   400000.000    48000.000

02D :   400000.000   266666.667    32000.000

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
hazelnusse
Associate III
Posted on July 12, 2011 at 02:30

Clive,

  Thanks for your responses.  I'm still a bit confused, it would be great if you could clarify a few of the things your wrote.

0) Can you explain what you mean by ''working at 320 KHz with 8 MHz multiple''.  I don't see where you are getting these numbers from.

1)  Where does the data sheet mention the input clock divider (2, 3, or 25 as you mentioned) for the I2C peripheral?  I don't see it anywhere in RM0008, is it somewhere else?

2) Is duty cycle part of I2C spec, or is this just something specific to the ST Peripheral?  The only related things I can find are minimum values for T_LOW and T_HIGH, which are 1.3 and .6 microseconds, respectively.  Maybe it is implied by the timings in their charts, but it isn't immediately obvious to me how the duty cycle is relevant.

Back to my original question:  is it possible to obtain a system clock of 72Mhz and use the I2C peripheral at 400khz?  Table 41 of the datasheet indicates that with a peripheral clock of 36Mhz (i.e., APB1 divider = 2), the I2C peripheral can be run at 400Khz by using I2C_CCR=0x801E.  The confusing part about this table is that it seems to a contradiction to the statement in the datasheet which says that in order to use fast mode at 400khz, the peripheral clock must be a multiple of 10Mhz, and 36Mhz clearly isn't.

Posted on July 12, 2011 at 15:22

''To use the I2C AT 400 KHz (in fast mode), the PCLK1 frequency (I2C peripheral input clock) must be a multiple of 10 MHz.''  Especially HEAVY emphasis of the word AT.

The peripheral doesn't care that it's a multiple of 10 MHz, it could be 9 MHz, or 8 MHz or whatever, and you'd have a safe rate of 360 KHz, and 320 KHz respectively.  10 MHz / 25 = 400 KHz.

The manual is lacking a clear diagram of how this works, but you can read between the lines, look at the library code, and think like an IC designer. There is a pretty clear and strong inference that they use a div 2, div 3 and div 25 to generate the timing, phase, and the math backs up this assertion. Look carefully at how they describe the duty timing behaviour.

The mode ST wants you to use divides the input clock by the value you program into CCR, a prescaler. This prescaled clock is then feed into 5-bit counter, the high order bit is used to separate the first 16 ticks, from the last 9, when the counter reaches 24 the next count is 0.  This provides you with the 16/9 duty cycle, it provides you with the 25 cycle count, and the 400 KHz * 25 = 10 MHz, with other source clocks you will not be able to reach exactly 400 KHz, but you can approach it.

However the prescaler feeds three possible counters to generate the I2C clock, the counter used is selected with a combination of the F/S bit, and the DUTY bit.

One of the alternate fast modes is a 2/1 duty cycle, a 2-bit counter, when the counter reaches 2 the next count is 0. To acheive 400 KHz, you need a source clock with a 1.2 MHz multiple (400 KHz * 3 = 1.2 MHz)

You'd need to review the I2C specificiations, or those of your slave parts, to understand if the duty cycle is important/critical. Remember that with Open-Drain the falling edges will be very rapid, the rising edges will be much more lazy, unless assisted, depending on the RC characteristics of the signal wires.

Goosing the duty of a clock is a simple trick to perform clock division by non power-of-twos, and keep the jitter to a minimum. There are other methods to perform fractional division, but these tend to result in jitter of the duty and period in the short term (phase noise), but very good long term frequency accuracy. Personally I doubt this is critically to I2C, as the timing is master driven, and very elastic.

The manual could be a lot clearer, like I said earlier the 10 MHz requirement is a limit of the 16/9 duty mode, it is far from clear that it impacts the other modes. You'd need to validate performance in your own application.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
hazelnusse
Associate III
Posted on July 12, 2011 at 20:14

Clive,

  Thanks for sharing your experience.  After repeated reads of the data sheet, I didn't extract the information you mention here, so I appreciate you taking the time to write such a detailed response.  I'm not an EE or a IC designer, so I definitely don't have as much of a ''feel'' for these things, but that is changing.

A quick search of ''I2C scl duty cycle'' wasn't too revealing, other than seeing that most people seem to be doing 50% duty cycle or something lower (i.e., SCL is high for less than half the time, as in the STM32 either 33% or 36% duty cycle).  I didn't see anybody discussing the opposite situation, where SCL is high for more than 50% of the time.

Is the main idea behind making SCL low for a longer portion of the overall period is that it gives a bit more time for the slave devices to release SDA?  This is an area of I2C that I haven't seen clear design guidelines for, and I'm not 100% what the implications of adjusting the duty cycle are, so if you know any good references, I'd love to see them.

Thanks again,

~Luke

can u please explain this?

It is a post from 7 years ago...

The 9 values in the table are I2C clocks, there are different CCR register settings down the left side, and the three columns relate to the options of "fast=0", "fast=1, duty=0" and "fast=1, duty=1"

Basically showing you the options to get the bus clocking at 400 KHz and 360 KHz when clocking the APB at 36 MHz

Peripheral clock = 36MHz
 
CCR    fst=0        fst=1,dty=0  fst=1,dty=1
 
004 :  4500000.000  3000000.000   360000.000
 
01E :   600000.000   400000.000    48000.000
 
02D :   400000.000   266666.667    32000.000

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..