TWI I2C driver gives success code but no data is sent

I have been working on writing a basic TWI driver in order to use I2C on my nRF52810 DK. I have the TWI successfully initializing, and when I try to write a byte to a connected device I get a success code. However, when I connect those pins to a scope I see no output whatsoever. I have tried connecting probes to different pins in case there is a discrepancy between what the pins are labeled on the development kit and which gpio they correspond to on the actual chip itself but still was unable to find anything. I've attached the relevant code below, any assistance would be greatly appreciated!

main.c

#include <zephyr.h>

#include "main.h"
#include "util/nrf52_util.h"

#define TCA6408_ADDR21 0x21
#define TCA6408ACDCselN  0x40

bool setDCcoupling() {
    //pulse the relay
    uint8_t readback;
    bool pass = true;
    readback = twi_read_byte(TCA6408_ADDR21);
    printk("Readback: %i\n", readback);
    twi_write_byte(TCA6408_ADDR21, readback | TCA6408ACDCselN);
    delay(100);
    return (pass);
}

int main(void) {
	init_delay_rtc();
    init_i2c(11, 12);

    setDCcoupling();

    // Uncomment for testing with scope
	// for (int i = 0; i < 1000; i++) {
    //     setDCcoupling();
    //     delay(1000);
	// }

    return 0;
}

nrf52_util.c

#include "nrf52_util.h"
#include <zephyr.h>

#define TWI_INSTANCE_ID 0 

static const nrfx_twi_t twi_instance = NRFX_TWI_INSTANCE(TWI_INSTANCE_ID);

nrfx_err_t init_i2c(int scl, int sda) {
    nrfx_twi_config_t twi_config = NRFX_TWI_DEFAULT_CONFIG(scl, sda);

    nrfx_err_t error_code = nrfx_twi_init(&twi_instance, &twi_config, NULL, NULL);

    nrfx_twi_enable(&twi_instance);

    return error_code;
}

bool twi_write_byte(uint8_t address, uint8_t data) {
    uint8_t tx_buffer[2];
    tx_buffer[0] = address;
    tx_buffer[1] = data;

    const nrfx_twi_xfer_desc_t transmit_desc = NRFX_TWI_XFER_DESC_TX(address, tx_buffer, sizeof(tx_buffer));

    while(nrfx_twi_is_busy(&twi_instance)) { }
    nrfx_err_t error_code = nrfx_twi_xfer(&twi_instance, &transmit_desc, 0);

    if (NRFX_SUCCESS != error_code) {
        printk("%i", error_code);
        printk("Failed to write byte.");
        return false;
    }
    printk("Successfully written byte: %x\n", data);
    return true;
}

uint8_t twi_read_byte(uint8_t address) {
    while(nrfx_twi_is_busy(&twi_instance)) { }
    uint8_t received_data = nrf_twi_rxd_get(twi_instance.p_twi);
    return received_data;
}

I see the message "Successfully written byte: 40" in my terminal but the device it is connected to isn't modified (the relay doesn't click, the status of the device doesn't update). I also see no signs of communication happening when I hook up a scope.

Parents
  • Hi,

    You will get NRFX_ERROR_INVALID_STATE from nrfx_twim_init() if it has already been initialized. I see from an include that you are using Zephyr (so I assume via nRF Connect SDK?). In that case, if you have enabled TWI in the device tree, the driver will be initialized automatically by the zephyr kernel behind the scenes. So if you want to use only the nrfx driver directly you should disable i2c in the device tree, for instance with an overlay where you set the status for i2c0 to disabled or set CONFIG_I2C=n in your prj conf (I believe either one of those two should be enough). There are some considerations when using nrfx drivers directly, so I suggest you refer to the nrfx use example if you want to do that (it is not specific for TWIM, though).

    That said, in most cases it would probably make more sense to use Zephyr's I2C API. That is explained in Lesson 6 – Serial communication (I2C) in the nRF Connect SDK Fundamentals course.

Reply
  • Hi,

    You will get NRFX_ERROR_INVALID_STATE from nrfx_twim_init() if it has already been initialized. I see from an include that you are using Zephyr (so I assume via nRF Connect SDK?). In that case, if you have enabled TWI in the device tree, the driver will be initialized automatically by the zephyr kernel behind the scenes. So if you want to use only the nrfx driver directly you should disable i2c in the device tree, for instance with an overlay where you set the status for i2c0 to disabled or set CONFIG_I2C=n in your prj conf (I believe either one of those two should be enough). There are some considerations when using nrfx drivers directly, so I suggest you refer to the nrfx use example if you want to do that (it is not specific for TWIM, though).

    That said, in most cases it would probably make more sense to use Zephyr's I2C API. That is explained in Lesson 6 – Serial communication (I2C) in the nRF Connect SDK Fundamentals course.

Children
No Data
Related