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.

MSP430FR2355: I2C creates two Start conditions

Part Number: MSP430FR2355
Other Parts Discussed in Thread: MSP430FR5994

The MSP430FR2355 creates I2C two start conditions after initialisation, so the first byte I send to an ADC is corrupted:

       image.png

The Code:

bool zssc3224_init(void)
{
    uint32_t tmpInt = 0;
    float FRES;

    // Init I2C
    GPIO_setOutputHighOnPin(AFE_POW_PIN); // Power on
    delay_ms(POWER_ON_DELAY);

    initMasterI2C(AFE_USCI_BASE, ZSSC3224_ADDRESS, DATARATE400KHZ); 

    GPIO_setAsPeripheralModuleFunctionOutputPin(AFE_SDA_PIN, AFE_PFX); // SDA
    GPIO_setAsPeripheralModuleFunctionOutputPin(AFE_SCL_PIN, AFE_PFX); // SCL

    enableI2C();

    // PMIN LSB
    if (!sendByteI2C(0x1E, true, true)) return (STATUS_FAIL);
    delay_ms(1);
    if (!receiveI2C(zssc3224_RxBuf,3)) return (STATUS_FAIL);
    if (!(zssc3224_checkState(zssc3224_RxBuf[0]) == STATUS_ZSSC_OK)) return STATUS_FAIL;
    tmpInt = 0;
    tmpInt = zssc3224_RxBuf[2];
    tmpInt <<= 8;
    tmpInt |= zssc3224_RxBuf[1];
    // PMIN MSB
    if (!sendByteI2C(0x1D, true, true)) return (STATUS_FAIL);
    delay_ms(1);
    if (!receiveI2C(zssc3224_RxBuf,3)) return (STATUS_FAIL);
    if (!(zssc3224_checkState(zssc3224_RxBuf[0]) == STATUS_ZSSC_OK)) return STATUS_FAIL;
    tmpInt <<= 8;
    tmpInt |= zssc3224_RxBuf[2];
    tmpInt <<= 8;
    tmpInt |= zssc3224_RxBuf[1];
    PMIN = int2float(tmpInt);
...

These are the I2C Routines

void initMasterI2C(uint16_t baseAddress, uint8_t slaveAddress, uint32_t datarate)
{
    I2C_USCI_BASE = baseAddress;
    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) = UCSWRST; 

    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW1) &= ~UCASTP_3;
    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW1) |= 0;
    HWREG16(I2C_USCI_BASE + OFS_UCBxTBCNT) = 0;

    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) |= UCMST + UCMODE_3 + UCSYNC;
    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) |= (UCSSEL__SMCLK + UCSWRST);

    uint16_t clkDiv = (uint16_t)(CS_getSMCLK() / datarate);
    HWREG16(I2C_USCI_BASE + OFS_UCBxBRW) = clkDiv;

    HWREG16(I2C_USCI_BASE + OFS_UCBxI2CSA) = (slaveAddress);
    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) |= UCTR;
}

void enableI2C(void)
{
    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) &= ~(UCSWRST);
}

bool sendStartI2C(void)
{
    uint32_t timeout;

    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) |= UCTXSTT; 

    timeout = I2C_TIMEOUT;

    while ((HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) & UCTXSTT) && --timeout);

    if (timeout == 0) return (STATUS_FAIL); // Timeout 

    return STATUS_SUCCESS;
}

bool sendStopI2C(void)
{
    uint32_t timeout;

    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) |= UCTXSTP; 

    timeout = I2C_TIMEOUT;
    while ((HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) & UCTXSTP) && --timeout); 
    if (timeout == 0) return (STATUS_FAIL);

    return STATUS_SUCCESS;
}

bool sendByteI2C(uint8_t data, bool sendStart, bool sendStop)
{
    uint32_t timeout;

    uint16_t txieStatus = HWREG16(I2C_USCI_BASE + OFS_UCBxIE) & UCTXIE;
    HWREG16(I2C_USCI_BASE + OFS_UCBxIE) &= ~(UCTXIE);

    HWREG16(I2C_USCI_BASE + OFS_UCBxCTLW0) |= UCTR; 

    if (sendStart)
    {
        if (!sendStartI2C()) return (STATUS_FAIL);
    }

    timeout = I2C_TIMEOUT;
    HWREG16(I2C_USCI_BASE + OFS_UCBxTXBUF) = data; 
    while ((!(HWREG16(I2C_USCI_BASE + OFS_UCBxIFG) & UCTXIFG)) && --timeout); 
    if (timeout == 0) return (STATUS_FAIL); 

    if (sendStop)
    {
        if (!sendStopI2C()) return (STATUS_FAIL);
    }

    HWREG16(I2C_USCI_BASE + OFS_UCBxIFG) &= ~(UCTXIFG); 
    HWREG16(I2C_USCI_BASE + OFS_UCBxIE) |= txieStatus; 

    return (STATUS_SUCCESS);
}

What could be the problem. I used this code on a MSP430FR5994 a lot without problems

  • 1) On the bus, I see a Start followed (immediately) by a Stop. As far as I know this is legal/benign in I2C, but it's rare enough that I suppose it might bother some slaves. 

    2) That said, I think this has to do with the use of GPIO_setAsPeripheralModuleFunctionOutputPin(), which sets the DIR before handing the pin to the I2C. Since the initial OUT register value is undefined, if it is =0 you'll get a brief low on the pin. I suggest using  GPIO_setAsPeripheralModuleFunctionInputPin() instead. This is what example eusci_b_i2c_ex1_MasterRxMultiple.c (e.g.) does.

    3) Unsolicited: The signatures I see for those two GPIO functions have 3 arguments (port, pins, mode), not 2. How does that code work exactly?

  • Yes, your right. Using GPIO_setAsPeripheralModuleFunctionOutputPin caused the Prpblem. Thank you very much.

    3) 

    #define  AFE_SDA_PIN    GPIO_PORT_P1, GPIO_PIN2
    #define  AFE_SCL_PIN    GPIO_PORT_P1, GPIO_PIN3
    #define  AFE_PFX            GPIO_PRIMARY_MODULE_FUNCTION

**Attention** This is a public forum