AVR 0/1 TWI Clock Generation

Go To Last Post
3 posts / 0 new
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The following is just trying to work out/understand how the twi baud calculation for avr0/1 fits together and looking for another pair of eyes to confirm or correct (pick out any avr0/1 datasheet for reference if wanted). I guess there are 10 clocks needed each SCL cycle that are unaccounted for in the BAUD register counting process (according to their formula). There could be errors below in the notes at bottom of post, but in the example with the Trise at max allowable 1us the Tlow ends up at 4us, add the 5 clocks I'll assume are unaccounted for (assuming symmetrical, so 10/2)- so that means Tlow = 4.5us. The i2c spec says the minimum Tlow needs to be 4.7us, so the calculated Tlow of 4.5us does not meet the spec. Where am I going wrong or is that correct?


There is a lot of timing requirements to be met, so I simply am after the big fish and assume the little fish will fall inline to some degree or can be checked later. Since Trise enters into the datasheet formula and is accounted for separate from Thigh, I assume that the baud counting is not starting until the 70%Vdd is reached for Thigh counting to start.


Maybe the flaw in the notes below is rearranging the formula to get BAUD and plugging in the wanted Fscl (atmel.start #define formula also does the same thing and ends up with the same numbers I calculated below). The datasheet never goes into calculating BAUD, and maybe for good reason. Using the wanted Fscl in the formula means the Fscl is calculated but the Tlow/Thigh requirements may still not be met.


Maybe the proper way to calculate baud should be based only on Tlow/Thigh requirements and the resulting Fscl is what you get, not necessarily what is wanted.


Since BAUD is used for Thigh and Tlow on the avr0/1, and there are presumably 5 Fper clocks unaccounted for on each, and since the Tlow requirement is larger than the Thigh requirement (4.7us vs 4.0us)- just need to come up with a BAUD value to meet the Tlow requirement-


BAUD = Fper * 4.7us - 5


using example numbers from notes below (10MHz Fper, 100kHz mode, Trise 1us)-

BAUD = 10MHz * 4.7us - 5 = 42

Fscl = 1 / (4.2us + 1us + 4.2us + 1us) = 96kHz

         Tlow + Trise + Thigh + 10clocks


Since 4.2us + 5clocks (0.5us) = 4.7us, the requirement has been met for Tlow and also Thigh (which only needs 4.0). Assuming Thigh counting (BAUD) is started at 70%Vdd, then Trise is only an external/analog requirement to be met and has nothing to do with the calculations (assumption is also based on the way they word Thigh as being timed by BAUD). 


Am I correct in thinking the BAUD calculation done below and in atmel.start is wrong? Or where is my thinking going wrong? If I am correct, then I would presume the mistake made was due to the assumption that rearranging the Fscl formula (as is typically done with formulas) could calculate BAUD based on a wanted Fscl when the result may not meet i2c requirements.




AVR 0/1 - TWI clock generation - Notes

orange = from datasheet


SCL x1 = Tfall + Tlow + Trise + Thigh


Tfall considered to be 0 since open-drain, so Tlow = Tfall+Tlow

Trise determined by bus characteristics (capacitance/pullup strength)


The BAUD field in TWIn.MBAUD value is used to time both SCL high and SCL low


Fper = peripheral clock (Fcpu)


Atmel Start (with 10Mhz clock specified)-

#define TWI0_BAUD(F_SCL, T_RISE) \

((((((float)10000000.0 / (float)F_SCL)) - 10 - ((float)10000000.0 * T_RISE / 1000000))) / 2)


Fscl = 1 / (Tlow + Trise + Thigh)

Fscl = Fper / ( 10 + 2BAUD + Fper*Trise )

rearranged (seems to be a mistake to do this)-

BAUD = ( (Fper/Fscl) - 10 - (Fper*Trise) ) / 2


Tbaud (Tlow,Thigh) = BAUD/Fper


Example - Fper = 10MHz, Fscl = 100kHz


--Trise = 0

BAUD = Fper/Fscl/2 - 5 = 45

Tlow = 45/Fper = 4.5us

Thigh = 45/Fper = 4.5us

Trise = 0us

Tclks10 = 10/Fper = 1us

Fscl = 1/(4.5us+0us+4.5us + 1us ) = 100kHz //Tlow = 4.5us+0.5us = ok


--Trise = 1us

BAUD = Fper/Fscl/2 - 5 - 10MHz*1us/2 = 40

Tlow = 40/Fper = 4us

Thigh = 40/Fper = 4us

Trise = 1us

Tclks10 = 10/Fper = 1us

Fscl = 1/(4us+1us+4us + 1us) = 100kHz //Tlow = 4us+0.5us = too low (need 4.7us)


NXP UM10204 (I2C Bus Specification)


Standard mode (100kHz)

Tlow - min 4.7us

Thigh - min 4.0us


  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Popular post. Not easy to follow, and now wonder why I wrote it. Since I cannot delete it, I'll try to not leave it hanging.


I did some testing, and it seems the datasheet formula works out and does make some sense. The ~10 clocks were also found (baud register at 0 will show them). I think I understand what is going on now to some degree.


Without getting into timing details outside the baud related ones, you basically have the clock limit of the mode in use (100kHz for standard mode), you also have Tlow and Thigh minimum times along with a max allowable Trise time. Tfall is considered to be 0 or insignificant because of the nature of the bus topology (strong pull down). The one baud register times both the Tlow and Thigh periods (and the Thigh count seems to start at 55% Vdd on the tiny817 tested).


no Trise-

[Thigh] [Tfall+Tlow] [Trise+Thigh]



If Trise is 0, the formula splits the time equally between Tlow/Thigh and you end up with BAUD timing half the clock period (and adjusted for the 5 clocks not accounted for). The Tlow and Thigh minimum times are satisfied (their combined total time is always less than 1/Fscl).


with Trise

[Thigh] [Tfall+Tlow] [Trise] [Thigh]



If Trise is lets say 1us (max for standard mode), now the formula removes the rise time and we are left splitting the remaining time equally between Tlow/Thigh (only one baud register doing double duty). Since Thigh has a shorter required minimum time than Tlow, it works out (the spec seems to be allowing most of the Trise to intrude on the Thigh time). Although it would appear that since the remaining time is split evenly, that Tlow could end up being too short but until 30%Vdd, Trise 'belongs' to Tlow so it still works out ok (i2c low/high levels are 30/70%).


An example with 1us rise time (internal pullup)- although the Tlow calculates to 4.5us (40+5) and is below minimum of 4.7us, it measures 4.92us using <30%Vdd as the low level. That means 0.42us of Trise is in the Tlow time and 0.65us is in the 30-70% Trise time. Although the baud counter starts counting prior to 70% (seems to be at 55% in this example mcu), the resulting Thigh time is still greater than the required 4us. Fscl Thigh, Tlow requirements are met.


    //int pullup. 10MHz fcpu, i2c standard mode (100kHz)
          1.4v            3.3v    Vdd=4.7v
    baud  Tlow    Trise   Thigh
    40    4.92us  1.07us  4.15us  10.14us 98.6kHz



IF you do NOT know the rise time, assume none and you will be fine (a little bit slower than you could be, but fine).


IF you assume a rise time that is larger than actual (you added stronger pullups for example) then you can get out of spec because your calculations accounted for rise time that does not exist (Tlow and Fscl goes out of spec). The mistake probably would only become a problem if assuming a large rise time, but actual rise time is quite short.


So, including rise time in the calculation gets you closer to your target speed (the more rise time, the better the calculation ends up helping). 


If you want to just forget about rise time, this define may be a little more friendly than the one produced by atmel.start (fits on one line, with no paren collection)-


#define TWI_BAUD(fcpu, fscl) fcpu/fscl/2 > 5 ? fcpu/fscl/2-5 : 0


TWI0.MBAUD  = TWI_BAUD(F_CPU, 100000);



My previous thoughts on baud calculation based on Tlow alone, works for meeting Tlow and Thigh requirements, but it can get out of Fscl specification (since Tlow is less than half 1/Fscl).




None of this is of any big significance, its just to get to a better understanding of how the baud register value works in the avr0/1.


  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the walk-through -




Until Black Lives Matter, we do not have "All Lives Matter"!