This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

I2C reads/writes: How to communicate with a 7bit I2C slave that has a 16bit memory map?

I am working with a sensor IC (IQS572) that communicates via I2C with my main microcontroller. Im using the nRF52382 chip. This sensor IC has a 7bit I2C slave address, but all of its internal registers that I want to read/write from have 16bit (2 byte) addresses. Most of my experience is with 8bit addressing schemes, so I am struggling a bit to set up my I2C/TWI code to properly configure this sensor IC. I have not been successful finding Nordic Forum posts that provide the answer I need. I have included my attempt for 16bit reads and writes below. twiRegRead16() seems to work as expected, but twiRegWrite16() doesnt seem to work.

The requirements from the sensor IC for an I2C write operation are as follows:

START, Slave Address + WRITE, ACK, Register Address HIGH, ACK, Register Address LOW, ACK, <data N>, ACK, <data n+1>, ACK, STOP

Notice there is no repeated START, as would be the case with the TXTX descriptor. Perhaps there is an easy way to prevent the repeated START for these specific writes?

uint32_t twiRegWrite16(uint8_t slaveAddr, uint16_t regAddr, uint8_t const * pdata, uint16_t length)
{
    uint32_t ret;
    uint8_t upperAddr = (regAddr >> 8) & 0x00FF;
    uint8_t lowerAddr = regAddr & 0x00ff;

    uint8_t tx_buff[2];
    tx_buff[1] = lowerAddr;
    tx_buff[0] = upperAddr;
    nrf_drv_twi_xfer_desc_t xfer;

    xfer.type = NRF_DRV_TWI_XFER_TX;
    xfer.address = slaveAddr;
    xfer.primary_length = sizeof(tx_buff);
    xfer.secondary_length = length;
    xfer.p_primary_buf = tx_buff;
    xfer.p_secondary_buf = pdata;
    m_xfer_status = 0;

    // NOTE: Could something as simple as this work instead?
    //uint8_t buffer[length + 2];
    //buffer[0] = upperAddr;
    //buffer[1] = lowerAddr;
    //memcpy(buffer + 2, pdata, length);
    //nrf_drv_twi_xfer_desc_t xfer = NRF_DRV_TWI_XFER_DESC_TX(slaveAddr, buffer, length + 1);

    ret = nrf_drv_twi_xfer(&m_twi, &xfer, 0);

    if (NRF_SUCCESS != ret)
    {
        return ret;
    }

    // Wait for response for 5 ms
    for(uint32_t k = 0; k <= 50; k++)
    {
        if(m_xfer_status != 0)
        {
            nrf_delay_ms(1);
            break;
        }
        nrf_delay_us(1);
    }

    if(m_xfer_status == TWI_XFER_STATUS_SUCCESS)
    {
        return NRF_SUCCESS;
    }
    else
    {
        return NRF_ERROR_INTERNAL;
    }
}


uint32_t twiRegRead16(uint8_t slaveAddr, uint16_t regAddr, uint8_t * pdata, uint16_t length)
{
    uint32_t ret;
    uint8_t tx_buff[2];

    m_xfer_status = 0;
    uint8_t upperAddr = (regAddr >> 8) & 0x00FF;
    uint8_t lowerAddr = regAddr & 0x00ff;
    tx_buff[1] = lowerAddr;
    tx_buff[0] = upperAddr;

    nrf_drv_twi_xfer_desc_t xfer = NRF_DRV_TWI_XFER_DESC_TXRX(slaveAddr, tx_buff, 2, pdata, length);
    ret = nrf_drv_twi_xfer(&m_twi, &xfer, 0);

    if (NRF_SUCCESS != ret)
    {
        return ret;
    }

    // Wait for response for 5 ms
    for(uint32_t k = 0; k <= 5000; k++)
    {
        if(m_xfer_status != 0)
        {
            nrf_delay_ms(1);
            break;
        }
        nrf_delay_us(1);
    }

    if(m_xfer_status == TWI_XFER_STATUS_SUCCESS)
    {
        return NRF_SUCCESS;
    }
    else
    {
        return NRF_ERROR_INTERNAL;
    }
}



Related