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

nRF52-DK / TWI does not send anything

I have some problems with the TWI (I2C) and it seems that TWI1 does not send anything. I have managed to create a simple example to recreate the issue. I am using TWI1 instead of TWI0, because I will need the other instance ID for the UART. I am using SES + nRF5 16.0.0 + nRF52-DK.

I am using the leds of the board to debug the issue. Leds 1 and 2 are turned on, but the program never receives event TXDSENT. When I look at the bus with a logic analyzer, there is no traffic at all. However, it seems that the bus is initialized correctly, because both the SCL and SDA (pins 9 and 10) are set high when the board is booted. I have also noticed that there is not even a start condition on the bus. Both the SCL and the SDA remain high.

Do you know what might be wrong?

#include <stdint.h>
#include <string.h>

#include "nrf_delay.h"
#include "nrf.h"
#include "nrf_gpio.h"

#define LED_1 17
#define LED_2 18
#define LED_3 19
#define LED_4 20

#define LED_ON  0
#define LED_OFF 1

#define I2C_SCL_PIN  9
#define I2C_SDA_PIN 10

void led_init (void)
{
    nrf_gpio_range_cfg_output(LED_1,LED_4);

    nrf_gpio_pin_write(LED_1,LED_OFF);
    nrf_gpio_pin_write(LED_2,LED_OFF);
    nrf_gpio_pin_write(LED_3,LED_OFF);
    nrf_gpio_pin_write(LED_4,LED_OFF);
}

void led (uint8_t led_id,uint8_t state)
{
    nrf_gpio_pin_write(led_id,state);
}

void i2c_init (void)
{
    NRF_TWI1->FREQUENCY = 0x01980000;     // 100 KHz

    NRF_TWI1->PSELSCL   = I2C_SCL_PIN;    // Pin  9, this is not a mask register!
    NRF_TWI1->PSELSDA   = I2C_SDA_PIN;    // Pin 10, this is not a mask register!
    
    NRF_TWI1->ADDRESS   = 0x40;           // Without read/write bit!

    NRF_TWI1->ENABLE    = 0x00000005;     // Enable
}

int main (void)
{
    led_init();
    i2c_init();

    led(LED_1,LED_ON);   // Debug LED 1

    NRF_TWI1->TASKS_STARTTX = 1;

    NRF_TWI1->TXD = 0xFE;

    led(LED_2,LED_ON);   // Debug LED 2

    while (NRF_TWI1->EVENTS_TXDSENT == 0)  { }

    NRF_TWI1->EVENTS_TXDSENT = 0;

    return 0;
}

  • I have also tested to set the pins manually in the beginning of i2c_init(). I have tried both with and without internal pullup resistors. The board has been connected to a digital temperature sensor (I2C). The temperature sensor has also pullup resistors (10K).

    nrf_gpio_cfg_input(I2C_SCL_PIN,NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_input(I2C_SDA_PIN,NRF_GPIO_PIN_PULLUP); 

    nrf_gpio_cfg_input(I2C_SCL_PIN,NRF_GPIO_PIN_NOPULL); 
    nrf_gpio_cfg_input(I2C_SDA_PIN,NRF_GPIO_PIN_NOPULL); 

  • It seems that the problem was caused by too long wires. I tested with really short wires and the I2C bus became active.

    However, there is still another problem. It seems that the hold time is very short, only about 0.5us. As a consequence, the sensor does not read the address correctly and it does not send an acknowledge. I tested the sensor with another MCU and the sensor worked fine. In this case, the hold time was about 2.5us.

    However, it seems that the issue is more related to the sensor than the MCU, because the I2C standard indeed indicates that the SDA must remain stable only when the SCL is high. I would still like to check if it is possible to adjust the TWI in any way to solve this issue.

  • This is indeed a sensor issue. I have tested the source code with another sensor and it sends an ACK successfully.

Related