This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR2675: I2C Master Write and Read without pData

Part Number: MSP430FR2675

Hello,

I am writing a couple of drivers for various sensors that the MSP430 is communicating with as an I2C master. I have the code below that I have been using to write/read data via the I2C. It has been working well.

I2CMaster_error_t I2CMaster_writeReg8(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *pData, uint8_t ui8Cnt)
{
    I2CMaster_error_t error;
    uint8_t count = UINT8_MAX;

    if (g_driver.state != I2CMaster_isIdle)
    {
        return eI2CMaster_unavailableError;
    }
    PrepForTransaction(ui8Addr, pData, ui8Cnt + 1);
    I2CMASTER__WRITEMODE;
    I2CMASTER__START;
    while (!(I2CMASTER__IFG & UCTXIFG) && 0 != count--)
    {
        if (g_driver.flags.ui8ErrorFlags != 0)
        {
            Cleanup();
            return CheckForErrors();
        }
    }
    assert(UINT8_MAX != count);
    I2CMASTER__TXBUF = ui8Reg;
    I2CMASTER__IE |= UCTXIE;
    error = FinishTransaction();
    return error;
}

I2CMaster_error_t I2CMaster_readReg8(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *pData, uint8_t ui8Cnt)
{
    I2CMaster_error_t error;
    uint8_t count = UINT8_MAX;

    if (g_driver.state != I2CMaster_isIdle)
    {
        return eI2CMaster_unavailableError;
    }
    PrepForTransaction(ui8Addr, pData, ui8Cnt);

    // Start communication by sending a start condition
    // and the slave bus address, and ensuring the slave
    // does not nack.
    I2CMASTER__WRITEMODE;
    I2CMASTER__START;
    while (!(I2CMASTER__IFG & UCTXIFG) && 0 != count--)
    {
        if (g_driver.flags.ui8ErrorFlags != 0)
        {
            Cleanup();
            return CheckForErrors();
        }
    }
    assert(UINT8_MAX != count);

    // Transmit the slave sub-register to read from
    I2CMASTER__TXBUF = ui8Reg;
    while (!(I2CMASTER__IFG & UCTXIFG) && 0 != count--)
    {
        // Handle the i8Cnt==1 case, where the stop bit is sent prematurely
        if (g_driver.flags.bStop == true)
        {
            break;
        }
        if (g_driver.flags.ui8ErrorFlags != 0)
        {
            Cleanup();
            return CheckForErrors();
        }
    }
    assert(UINT8_MAX != count);

    // Read out the data from the slave
    g_driver.flags.ui8StatusFlags = 0;
    I2CMASTER__READMODE;
    I2CMASTER__START;
    I2CMASTER__IE |= UCRXIE;
    error = FinishTransaction();

    return error;
}

I2CMaster_error_t CheckForErrors(void)
{
    if (g_driver.flags.bClockLowTimeout == true)
    {
        return eI2CMaster_busTimeoutError;
    }
    else if (g_driver.flags.bSlaveNack == true)
    {
        return eI2CMaster_slaveNackError;
    }
    else
    {
        return eI2CMaster_noError;
    }
}

void PrepForTransaction(uint8_t ui8Addr, uint8_t *pData, uint8_t ui8Cnt)
{
    I2CMASTER__SET_RST;
    g_driver.state = I2CMaster_isCommunicating;
    g_driver.flags.ui8AllFlags = 0;
    g_driver.pData = pData;
    I2CMASTER__I2CSA = ui8Addr;
    I2CMASTER__TBCNT = ui8Cnt;
    I2CMASTER__CLEAR_RST;
    I2CMASTER__IE = UCNACKIE | UCCLTOIE | UCSTPIFG;
}

void Cleanup(void)
{
    I2CMASTER__IE = 0;
    g_driver.state = I2CMaster_isIdle;
}

I2CMaster_error_t FinishTransaction(void)
{
    uint8_t count = UINT8_MAX;
    while (g_driver.flags.bStop == false && 0 != count--)
    {
        if (g_driver.flags.ui8ErrorFlags != 0)
        {
            Cleanup();
            return CheckForErrors();
        }
    }
    assert(UINT8_MAX != count);
    Cleanup();
    return CheckForErrors();
}

However, I have a sensor that functions a little differently compared to what this code is doing. I have attached a screenshot of how it works. In essence, I need to be able to write to an I2C register without any pData associated with it. Then, I need to send a read to the I2C address without setting a register. For example, if the address of the sensor is 0x50 and I want to read data from register 0x7F, then I would first send a write command to register 0x7F that looks like 0x50 0x7F followed by a read command to 0x50 where I would receive the desired data.

Is there a way to edit my code in order to run these commands?

Thanks,

Eric

  • Have you tried issuing your request using readReg8 with ui8Reg=command? Even though the diagram shows a Stop after the command, it might be OK with a repeated-Start instead.

    If the device really insists on the "command" request ending with a Stop, you probably need a separate i2c_readdata() which only does the second half of readReg8; then you would call writeReg8 with ui8reg=command and ui8cnt=0, followed by i2c_readdata().

  • Hi Bruce,

    Thanks for your suggestion. I have tried for now to do the readReg8 and will see if that works. I will be able to test that within the next week or two. If that doesn't work, I will see if your other suggestion works.

    Thanks.

  • Hi Eric,

    Any update about this thread, do you need other support?

    Thanks!

    Best Regards

    Johnson

**Attention** This is a public forum