cancel
Showing results for 
Search instead for 
Did you mean: 

HSI I2C Accuracy

tomm5771
Associate II

I am trying to use the 16 MHz HSI as the clock source for I2C. When I set up the I2C_TIMINGR bits for 100kbps I2C, everything works fine. When I try to set up for 400kbps, it still works, but the timing is not 400kbps. Does the accuracy of the HSI decrease when using I2C at higher speeds? The I2C speed comes out to around 300 kbps when using the HSI. I am setting the I2C_TIMINGR register so that the SCLH and SCLL are both 0x13 (19 decimal) because if you plug this into the formula provided, it comes out to have both the high and low part of the I2C clock to 1.25 usec. SCLH is the high part of the clock, SCLL is the low part of the clock.

Formulas are tSCLH = (SCLH + 1) x tPRESC and tSCLL  = (SCLL + 1) x tPRESC. tPRESC is 62.5 nsec. I am setting both SCLH and SCLL to 0x13 and am expecting to get 1.25 usec. That is not what it is coming out to when I look at I2C traffic on a scope. 

 

11 REPLIES 11
TDK
Guru

I2C timing is not exact in general. There's no way to force exactly 100 kHz or 400 kHz. This is due to the requirements of the I2C protocol and how it has to wait for edges to happen.

If your edges are slow, expect slower timing. However, slower timing is not necessarily an issue except throughput will be slower.

Showing the I2C traces would be informative.

HSI will not become more or less accurate depending on I2C settings as it is independent of the I2C peripheral.

If you feel a post has answered your question, please click "Accept as Solution".
BarryWhit
Senior III

> If your edges are slow, expect slower timing.

Then would configuring the GPIO output speed register appropriately would really affect the bus speed significantly (i.e. 25%)? Why would slow edges matter so much at a freq as low as 400KHz?

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

Selecting HSI or any other clock source for I2C peripheral should not be the issue. The I2C timing is set by programming all these parameters, like tSCLH and all the other parameters.

I could bring I2C working up to 3 MHz, but the trick is: you have to tweak these values. I suggest to use an oscilloscope and measure the clock speed, trim the value.

You have to consider also, that on faster I2C clock speeds you cannot use anymore the analog filter.

It should be possible to trim the I2C clock speed, not really exactly to 400 KHz, but in this region.
The setup and hold times affect also the I2C clock speed. So, all parameters have an effect. Just play with it until you are close to the speed you want.

BTW:
In my systems, I use setup values which I have verified with a scope. Later, I select the speed by choosing 0..X as enumerator and grab the correct config value. Just calculating back from a requested frequency to a config value was never successful: I had to tweak via all the other parameters, also playing with the duty cycle.

GPIO output speed will affect the falling edge but not the rising edge. The rising edge is much slower and is likely the issue here. Pins are in output drain mode for I2C.

If you feel a post has answered your question, please click "Accept as Solution".
BarryWhit
Senior III

You're the Guru. But this still strikes me as odd unless there is some peculiarity of I2C I'm not aware off (quite possible).

 

Take a conservative estimate of rise time as being 1/20 of the clock period.

For 400Khz that would be 1/(20*400e3) = 125ns. That's a very slow edge for any remotely modern process, and that's a conservative estimate of a "good enough" rise-time. Wouldn't the GPIO buffer's edge have to be implausibly slow, to drag down the clock period from 400Khz to 300Khz....?

 

Also, tjaekel suggests that you can tweak timing params to dial in the bus frequency and get quite close that way. But if the formulas provided by ST for choosing the timing values in order to get a target frequency result in being off by 25%, something must be wrong, mustn't it?

 

HSI is not meant to be very accurate, but at room temp is still spec'd to within a few percent, which in itself would not explain this issue. There's a known issue about the HSI  frequency drifting from nominal during assembly due to thermal cycle (AN5067), but the mean of that error is only about 0.6%, so it doesn't explain this either.

 

Am I missing something?

 

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

GPIOs are in open drain mode. Only external pullup resistor and trace capacity set duration of rising edge. MCU does not know how long it takes and not even measure rise time duration to be able maintain exact communication speed - because it is not normally needed. ST timing formula count with these rise times, but tomm5771 probably forgot to count them.

BarryWhit
Senior III

Good. So you're saying the root cause of the OP might be that he is using Pull-up resistors that are too large.

 

@tomm5771  , is that the case?

 

(I accept that 300kz vs. 400khz may not be important in many typical I2C applications, it's just nice to know why this is happening)

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

Not exactly. He just probably forgot to count his actual rising times in timing settings.

BarryWhit
Senior III

@tomm5771 , CubeMX will calculate a value for I2C_TIMINGR for you, based on rise time and fall time in your circuit. Try using it to calculate the proper values for tSCLH/tSCLL.

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.