This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TWI speed not correct

Hello DevZone,

I was tinkering around with the speed of the TWIM0 module in the nRF52832.

I have a cheap USB logic analyzer to help me display the waveforms and I made a discovery.

Testing the TWIM0 with 100kbps results this:

Perfect 100kHz clock signal.

Testing the TWIM0 with 250kbps results this:

Uneven duty cycle 250kHz clock but still spot on.

Testing the TWIM0 with 400kbps results this:

Euh.. Wait, that's a 200kHz signal, how is this possible. TWI isn't ment to do double data rate :)

Checking out the datasheet on the clock rate I see that at 400kbps the frequency value should be 0x06400000. Looking in the nrf52_bitfields.h I see that the 400kbps clock is defined as #define TWI_FREQUENCY_FREQUENCY_K400 (0x06680000UL) /*!< 400 kbps (actual rate 410.256 kbps) */

Writing the datasheet value of 0x06400000 does not change the frequency to 400kHz but  slightly lower than 200kHz.

I've tested some different values to see what output frequency I get and this is what I got

0x01000000 -> 62.5kHz
0x08000000 -> 250kHz
0x08880000 -> 266.67kHz
0x0A880000 -> 333.33kHz
0x0C880000 -> 400kHz
0x10000000 -> strange waveform at 500kHz
0x20000000 -> unstable waveform at 1MHz (could be that my slave could not keep up properly.
0x40000000 -> 666.67kHz

Is anyone able to explain this to me? Could this be a silicon bug as I did not test it on a other nRF52832?

Is there any information how this variable is handled within the TWI module and how it is possible to get frequencies which are out of spec from the nRF52832?

Kind regards,

T IJ

  • I compiled the twi scanner example:
    \nRF5_SDK_15.3.0_59ac345\examples\peripheral\twi_scanner

    Then modified twi_init():

    void twi_init (void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_config = {
           .scl                = ARDUINO_SCL_PIN,
           .sda                = ARDUINO_SDA_PIN,
           .frequency          = NRF_DRV_TWI_FREQ_400K,
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_twi, &twi_config, NULL, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_gpio_cfg_input(ARDUINO_SCL_PIN, NRF_GPIO_PIN_PULLUP);
        nrf_gpio_cfg_input(ARDUINO_SDA_PIN, NRF_GPIO_PIN_PULLUP);
    
        nrf_drv_twi_enable(&m_twi);
    }

  • This is my code how I use the TWI

        const nrf_twi_config_t twi_config = {.scl = 25,
            .sda = 24,
            .frequency = 0x0c880000, //TWI_FREQUENCY_FREQUENCY_K400,
            .interrupt_priority = 2};
    
        twi_setup(NRF_TWIM0, &twi_config);
    
    
    void twi_setup(NRF_TWIM_Type * p_twim, nrf_twi_config_t const * p_config)
    {
        NRFX_ASSERT(p_twim);
        NRFX_ASSERT(p_config);
        NRFX_ASSERT(p_config->scl != p_config->sda);
        nrf_twim_disable(p_twim);
    
        NRF_P0->PIN_CNF[p_config->scl] =
            (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) & GPIO_PIN_CNF_DRIVE_Msk |
            GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos;
        NRF_P0->PIN_CNF[p_config->sda] =
            (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) & GPIO_PIN_CNF_DRIVE_Msk |
            GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos;
        NRF_P0->DIRCLR = (1 << p_config->scl) | (1 << p_config->sda);
    
        nrf_twim_pins_set(p_twim, p_config->scl, p_config->sda);
    
        nrf_twim_frequency_set(p_twim, p_config->frequency);
    
        nrf_twim_int_enable(p_twim, NRF_TWIM_INT_STOPPED_MASK | NRF_TWIM_INT_ERROR_MASK);
    
        NVIC_SetPriority(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, p_config->interrupt_priority);
        NVIC_EnableIRQ(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn);
    
        nrf_twim_enable(p_twim);
    }

    And still I only get 200kbps if I use the TWI_FREQUENCY_FREQUENCY_K400 macro.

    I dont know if I done something odd in my code or not.

  • Can you try the SDK example as suggested?

    Kenneth

  • Sorry for the late response, had some hospital stuff to do.

    I've tried the TWI scanner and it resulted in the same speed. 200kbps with 400kbps settings.

    I'm using SDK 15.0, I  dont know if this makes the difference.

  • I've had a similar issue. I think I found the source of the issue: the chip's TWIM clock stretching. I'm unfamilar of how the internal chip circuitry works, but I noticed when I added a longer wire to my circuit, all of a sudden the clock rate went from 250kHZ to 125kHz (with the master frequency set to 250kHz). Just by adding a wire! The additional capacitance must have some effect on the clock stretching circuit.

    Just speculating, but the theory would be the slow rise times fool the TWIM into thinking a peripheral is clock stretching, so the TWI skips a clock cycle until the clock line rises back again.

    For workarounds, try using a larger pull-up resistor.

Related