Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: I2C maximum speed

  1. #1
    Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    86

    I2C maximum speed

    Hi all,

    For my projects I must know the maximum speed of the I2C bus Teensy 4 this is needed to read my external A/D converter.

    If someone know please replay.

    Best regards,
    Johan

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,439
    If you use the Wire library, 1 MHz is the fastest speed it supports. Of course, you'll need strong pullup resistors and moderate to short length wires and not many chips connected for the signals to actually work that fast.

    If you hack the WireIMXRT.cpp or directly write to the MCCR0, MCFGR1, MCFGR2 registers, I hope you'll share anything you learn about the actual practical speed limits. The speed setting in this new chip isn't just 1 simple number. It's a bunch of settings that control various timing aspects of the waveform. Details can be found in the chip's reference manual.

    Here's the code you'll find inside WireIMXRT.cpp:

    Code:
            if (frequency < 400000) {
                    // 100 kHz
                    port->MCCR0 = LPI2C_MCCR0_CLKHI(55) | LPI2C_MCCR0_CLKLO(59) |
                            LPI2C_MCCR0_DATAVD(25) | LPI2C_MCCR0_SETHOLD(40);
                    port->MCFGR1 = LPI2C_MCFGR1_PRESCALE(1);
                    port->MCFGR2 = LPI2C_MCFGR2_FILTSDA(5) | LPI2C_MCFGR2_FILTSCL(5) |
                            LPI2C_MCFGR2_BUSIDLE(3900);
            } else if (frequency < 1000000) {
                    // 400 kHz
                    port->MCCR0 = LPI2C_MCCR0_CLKHI(26) | LPI2C_MCCR0_CLKLO(28) |
                            LPI2C_MCCR0_DATAVD(12) | LPI2C_MCCR0_SETHOLD(18);
                    port->MCFGR1 = LPI2C_MCFGR1_PRESCALE(0);
                    port->MCFGR2 = LPI2C_MCFGR2_FILTSDA(2) | LPI2C_MCFGR2_FILTSCL(2) |
                            LPI2C_MCFGR2_BUSIDLE(3900);
            } else {
                    // 1 MHz
                    port->MCCR0 = LPI2C_MCCR0_CLKHI(9) | LPI2C_MCCR0_CLKLO(10) |
                            LPI2C_MCCR0_DATAVD(4) | LPI2C_MCCR0_SETHOLD(7);
                    port->MCFGR1 = LPI2C_MCFGR1_PRESCALE(0);
                    port->MCFGR2 = LPI2C_MCFGR2_FILTSDA(1) | LPI2C_MCFGR2_FILTSCL(1) |
                            LPI2C_MCFGR2_BUSIDLE(3900);
            }
    If you reduce those numbers, it very likely will run faster. How good the waveforms really look, or how reliably it really works is a good question. The reality is Teensy 4.0 is very new. So far it's only been tested with those 3 settings. As far as I know, nobody using this forum has really tested it at other settings. I know I sure haven't. But I did run tests with all 3 of those settings during the beta test. 1 MHz definitely does work.

  3. #3
    Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    86
    Hi all,

    I like to run my AD7991 I2C on 1MHz Paul says change some numbers but what to change to get 1MHz for the I2C bus? In my case I use SDA1 an SCL1..

    Best,
    Johan

  4. #4
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,129
    Quote Originally Posted by pd0lew View Post
    Hi all,

    I like to run my AD7991 I2C on 1MHz Paul says change some numbers but what to change to get 1MHz for the I2C bus? In my case I use SDA1 an SCL1..

    Best,
    Johan
    Wire1.setClock(1000000)

  5. #5
    Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    86
    void setup()
    {

    Wire1.setClock(1000000) ;
    Right ?

  6. #6
    Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    86
    Hi, I don't think it's that simple for a Teensy 4.... see picture
    about 100KHz

    Click image for larger version. 

Name:	DeepinScreenshot_select-area_20190827192253.png 
Views:	9 
Size:	129.4 KB 
ID:	17342
    Best,
    Johan

  7. #7
    Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    86
    The maximum I can get is 375 KHz, instead of 1MHz.......


    void TwoWire::setClock(uint32_t frequency)
    {
    port->MCR = 0;
    if (frequency < 100000) {
    // 100 kHz
    port->MCCR0 = LPI2C_MCCR0_CLKHI(55) | LPI2C_MCCR0_CLKLO(59) |
    LPI2C_MCCR0_DATAVD(25) | LPI2C_MCCR0_SETHOLD(40);
    port->MCFGR1 = LPI2C_MCFGR1_PRESCALE(1);
    port->MCFGR2 = LPI2C_MCFGR2_FILTSDA(5) | LPI2C_MCFGR2_FILTSCL(5) |
    LPI2C_MCFGR2_BUSIDLE(3900);
    } else if (frequency < 1000000) {
    // 400 kHz
    port->MCCR0 = LPI2C_MCCR0_CLKHI(26) | LPI2C_MCCR0_CLKLO(28) |
    LPI2C_MCCR0_DATAVD(12) | LPI2C_MCCR0_SETHOLD(18);
    port->MCFGR1 = LPI2C_MCFGR1_PRESCALE(0);
    port->MCFGR2 = LPI2C_MCFGR2_FILTSDA(2) | LPI2C_MCFGR2_FILTSCL(2) |
    LPI2C_MCFGR2_BUSIDLE(3900);
    } else {
    // 1 MHz
    port->MCCR0 = LPI2C_MCCR0_CLKHI(9) | LPI2C_MCCR0_CLKLO(10) |
    LPI2C_MCCR0_DATAVD(4) | LPI2C_MCCR0_SETHOLD(7);
    port->MCFGR1 = LPI2C_MCFGR1_PRESCALE(0);
    port->MCFGR2 = LPI2C_MCFGR2_FILTSDA(1) | LPI2C_MCFGR2_FILTSCL(1) |
    LPI2C_MCFGR2_BUSIDLE(3900);
    }
    port->MCCR1 = port->MCCR0;
    port->MCFGR0 = 0;
    port->MCFGR3 = LPI2C_MCFGR3_PINLOW(3900);
    port->MFCR = LPI2C_MFCR_RXWATER(1) | LPI2C_MFCR_TXWATER(1);
    port->MCR = LPI2C_MCR_MEN;
    }

    #endif

  8. #8
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,129
    Quote Originally Posted by pd0lew View Post
    Hi, I don't think it's that simple for a Teensy 4.... see picture
    about 100KHz
    Best,
    Johan
    Works for me. you need to do Wire1.setClock() after Wire1.begin()
    With nothing connected to I2C pins and runnning I2C Scanner, scope shows 86 khz for clock 100khz, 238khz for clock 400khz, 380khz for clock 1mhz. With BMP085 breakout (10k pullups), scope shows 96KHz for I2C clock @100KHz, 325KHz for clock @400KHz, and 625KHz for clock 1MHz. Adding 2.2Kohm pullups in parallel on SDA and SCL, scope shows 99.2khz @100khz, 379khz @400khz, and 893khz @1mhz.
    Last edited by manitou; 08-28-2019 at 10:07 AM.

  9. #9
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,129
    Quote Originally Posted by pd0lew View Post
    The maximum I can get is 375 KHz, instead of 1MHz.......
    It's not uncommon for the actual clock rate to be less than requested on T3* and T4 and maybe many other MCU's. You can try and hack the core I2C driver code to increase the I2C clock closer to your target (read ref manual). But as Paul noted, changing I2C clock may also require changing high and low times for SDA and SCL waveforms.

    early in T4 beta testing, i experimented with I2C clock (pins 18,19) see
    https://forum.pjrc.com/threads/54711...l=1#post194538
    scope measured 926KHz with I2C@1MHz
    Last edited by manitou; 08-27-2019 at 07:11 PM.

  10. #10
    Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    86
    I think there can be a clear answer to the I2C bus instead of reading 1000 pages.

    This needs more research....

    Click image for larger version. 

Name:	DeepinScreenshot_select-area_20190827202305.jpg 
Views:	13 
Size:	147.2 KB 
ID:	17343

  11. #11
    Member Rena's Avatar
    Join Date
    Oct 2014
    Location
    Cambridge, Ontario, Canadia
    Posts
    32
    I2C can be pretty finicky. In your graph it looks like you have some bus capacitance which will interfere with the signal.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •