Because of the Thanksgiving holiday in the U.S., TI E2E™ design support forum responses may be delayed from November 25 through December 2. Thank you for your patience.

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.

MSP432P401R: With DAC121C085 I2C Problem

Part Number: MSP432P401R

I am trying to use DAC121C081 with msp432p401R. but at debug mode software stucks at while (I2C_isBusBusy(EUSCI_B3_BASE));

int main(){

        Init_I2C_GPIO();
        I2C_init();
        I2C_setslave(0x0C);
        I2C_write16(0x0, 4096);
}

const eUSCI_I2C_MasterConfig i2cConfig =
{
        EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
        48000000,                               // SMCLK = 48MHz
        EUSCI_B_I2C_SET_DATA_RATE_400KBPS,      // Desired I2C Clock of 100khz
        0,                                      // No byte counter threshold
        EUSCI_B_I2C_NO_AUTO_STOP                // No Autostop
};

void Init_I2C_GPIO()
{
    /* Select I2C function for I2C_SCL(P6.7) & I2C_SDA(P6.6) */
    GPIO_setAsPeripheralModuleFunctionOutputPin(
            GPIO_PORT_P6,
            GPIO_PIN7,
            GPIO_PRIMARY_MODULE_FUNCTION);

    GPIO_setAsPeripheralModuleFunctionOutputPin(
            GPIO_PORT_P6,
            GPIO_PIN6,
            GPIO_PRIMARY_MODULE_FUNCTION);
}


/***************************************************************************//**
 * @brief  Configures I2C
 * @param  none
 * @return none
 ******************************************************************************/

void I2C_init(void)
{
        /* Initialize USCI_B3 and I2C Master to communicate with slave devices*/
    I2C_initMaster(EUSCI_B3_BASE, &i2cConfig);

    /* Disable I2C module to make changes */
    I2C_disableModule(EUSCI_B3_BASE);

    /* Enable I2C Module to start operations */
    I2C_enableModule(EUSCI_B3_BASE);

    return;
}


/***************************************************************************//**
 * @brief  Reads data from the sensor
 * @param  writeByte Address of register to read from
 * @return Register contents
 ******************************************************************************/

int I2C_read16(unsigned char writeByte)
{
    volatile int val = 0;
    volatile int valScratch = 0;

    /* Set master to transmit mode PL */
    I2C_setMode(EUSCI_B3_BASE,
        EUSCI_B_I2C_TRANSMIT_MODE);

    /* Clear any existing interrupt flag PL */
    I2C_clearInterruptFlag(EUSCI_B3_BASE,
        EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

    /* Wait until ready to write PL */
    while (I2C_isBusBusy(EUSCI_B3_BASE));

    /* Initiate start and send first character */
    I2C_masterSendMultiByteStart(EUSCI_B3_BASE, writeByte);

    /* Wait for TX to finish */
    while(!(I2C_getInterruptStatus(EUSCI_B3_BASE,
        EUSCI_B_I2C_TRANSMIT_INTERRUPT0)));

    /* Initiate stop only */
    I2C_masterSendMultiByteStop(EUSCI_B3_BASE);

    /* Wait for Stop to finish */
    while(!I2C_getInterruptStatus(EUSCI_B3_BASE,
        EUSCI_B_I2C_STOP_INTERRUPT));

    /*
     * Generate Start condition and set it to receive mode.
     * This sends out the slave address and continues to read
     * until you issue a STOP
     */
    I2C_masterReceiveStart(EUSCI_B3_BASE);

    /* Wait for RX buffer to fill */
    while(!(I2C_getInterruptStatus(EUSCI_B3_BASE,
        EUSCI_B_I2C_RECEIVE_INTERRUPT0)));

    /* Read from I2C RX register */
    val = I2C_masterReceiveMultiByteNext(EUSCI_B3_BASE);

    /* Receive second byte then send STOP condition */
    valScratch = I2C_masterReceiveMultiByteFinish(EUSCI_B3_BASE);

    /* Shift val to top MSB */
    val = (val << 8);

    /* Read from I2C RX Register and write to LSB of val */
    val |= valScratch;

    /* Return temperature value */
    return (int16_t)val;
}


/***************************************************************************//**
 * @brief  Writes data to the sensor
 * @param  pointer  Address of register you want to modify
 * @param  writeByte Data to be written to the specified register
 * @return none
 ******************************************************************************/

void I2C_write16 (unsigned char pointer, unsigned int writeByte)
{
    /* Set master to transmit mode PL */
    I2C_setMode(EUSCI_B3_BASE,
        EUSCI_B_I2C_TRANSMIT_MODE);

    /* Clear any existing interrupt flag PL */
    I2C_clearInterruptFlag(EUSCI_B3_BASE,
        EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

    /* Wait until ready to write PL */
    while (I2C_isBusBusy(EUSCI_B3_BASE));

    /* Initiate start and send first character */
    I2C_masterSendMultiByteStart(EUSCI_B3_BASE,
        pointer);

    /* Send the MSB to SENSOR */
    I2C_masterSendMultiByteNext(EUSCI_B3_BASE,
        (unsigned char)(writeByte>>8));

    I2C_masterSendMultiByteFinish(EUSCI_B3_BASE,
        (unsigned char)(writeByte&0xFF));

}


void I2C_setslave(unsigned int slaveAdr)
{
    /* Specify slave address for I2C */
    I2C_setSlaveAddress(EUSCI_B3_BASE,
        slaveAdr);

    /* Enable and clear the interrupt flag */
    I2C_clearInterruptFlag(EUSCI_B3_BASE,
        EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    return;
}

  • Hi,

    unfortunately the logic is inverted on the I2C_isBusBusy function
    so the proper usage would be
    while (I2C_isBusBusy(EUSCI_B3_BASE) == EUSCI_B_I2C_BUS_BUSY);

    See also the documentation of the I2C driver lib functions:

    //
    //! Indicates whether or not the I2C bus is busy.
    //!
    //! \param moduleInstance is the instance of the eUSCI B (I2C) module. Valid
    //! parameters vary from part to part, but can include:
    //! - \b EUSCI_B0_BASE
    //! - \b EUSCI_B1_BASE
    //! - \b EUSCI_B2_BASE
    //! - \b EUSCI_B3_BASE
    //! <br>It is important to note that for eUSCI modules, only "B" modules such as
    //! EUSCI_B0 can be used. "A" modules such as EUSCI_A0 do not support the
    //! I2C mode.
    //!
    //!
    //! This function returns an indication of whether or not the I2C bus is
    //! busy.This function checks the status of the bus via UCBBUSY bit in
    //! UCBxSTAT register.
    //!
    //! \return Returns EUSCI_B_I2C_BUS_BUSY if the I2C Master is busy; otherwise,
    //! returns EUSCI_B_I2C_BUS_NOT_BUSY.
    //
    //*****************************************************************************

    Regards,
    Stefan
  • Thank you. now it stucks again at a "while" in the I2C_masterSendMultiByteStart(EUSCI_B3_BASE, pointer); function.

    while (BITBAND_PERI(EUSCI_B_CMSIS(moduleInstance)->CTLW0,
                    EUSCI_B_CTLW0_TXSTT_OFS)
                    || !BITBAND_PERI(EUSCI_B_CMSIS(moduleInstance)->IFG,
                            EUSCI_B_IFG_TXIFG0_OFS));

  • Hi,

    do you have an option to probe the two lines for I2C (SDA and SCL) and send scope screenshot of this start sequence there.

    Also looking into the DAC datasheet it shows that when access the DAC only two data bytes should be transferred. The Address mentioned there is the I2C address. In your code you always send 3 bytes: pointer and writeByte (low and high byte)

    Regards,
    Stefan
  • after Init_I2C_GPIO(); both pins become 0.04V before that function they are at 1.2V. This is odd right ?
  • Hi,
    Right it is odd but also clarifies the problem.
    The I2C functions is the secondary function on that pins. So you have to call:
    void Init_I2C_GPIO()
    {
    /* Select I2C function for I2C_SCL(P6.7) & I2C_SDA(P6.6) */
    GPIO_setAsPeripheralModuleFunctionOutputPin(
    GPIO_PORT_P6,
    GPIO_PIN7,
    GPIO_SECONDARY_MODULE_FUNCTION);

    GPIO_setAsPeripheralModuleFunctionOutputPin(
    GPIO_PORT_P6,
    GPIO_PIN6,
    GPIO_SECONDARY_MODULE_FUNCTION);
    }

    Regards,
    Stefan
  • now pins are always 1.2v but still stucks at same code.
  • OK, small step but going forward.
    So 1.2 V is definite to low. It show go up to the supply voltage.
    Can you first check that the supply voltage is OK at 3.3V as shown in your schematic.
    Next can you check the voltage level on the I2C pins after reset and during stepping through the initialization .

    Regards,
    Stefan
  • 3.3V is ok. just like the schematic. other pin of resistor is 3.3v but i2c pins are 1.2v and it doesnt change after Init_I2C_GPIO();
  • So you may need to check your board
    -> before initializing the port pins the pins are configured as inputs. Therefore no load is on the pins from the MSP432 side. But with the values given it looks like a 2.7k Ohm (real or virtual) is pulling the I2C lines low against the 4.7k you have on your schematic.

    Regards,
    Stefan

  • Ok, i have found the problem. now pins are 3.3V and at first it doesnt stuck but output was stil 0. and now it stucks again. I didnt write this code. It is one of yours. Tried to adapt for dac121c085 but i think i failed.

  • Before device is initialized the Pin on the MSP432 is input and that does not give any load on the pin.
    But as you see the line at 1.2V with pull up resistor of 4.7k there must be somewhere another load to GND over a resistor of ~ 2.8k Ohm

    Rx = 4k7 Ohm / (3.3V - 1.2V) * 1.2V

    This must be somewhere on your board.

    Regards,
    Stefan
  • Ok there is no problem now. Codes working fine. But the output doesnt change. i think the commands are wrong. Could you help me with that too ?
  • OK, I2C seems to work - a big step into the right direction.

    Looking into the DAC datasheet i think your send routine should be like this (see also DAC Register chapter in http://www.ti.com/lit/ds/symlink/dac121c085.pdf)

    void I2C_write16 (unsigned char pointer, unsigned int writeByte)
    {
        /* Set master to transmit mode PL */
        I2C_setMode(EUSCI_B3_BASE,
            EUSCI_B_I2C_TRANSMIT_MODE);
    
        /* Clear any existing interrupt flag PL */
        I2C_clearInterruptFlag(EUSCI_B3_BASE,
            EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
        /* Wait until ready to write PL */
        while (I2C_isBusBusy(EUSCI_B3_BASE));
    
        /* Initiate start and send first character */
        I2C_masterSendMultiByteStart(EUSCI_B3_BASE,
            (unsigned char)( ((writeByte>>8) & 0x0F) | ((pointer << 4) & 0x30) ) );
    
    
        I2C_masterSendMultiByteFinish(EUSCI_B3_BASE,
            (unsigned char)(writeByte & 0xFF));
    
    }
    
    Note1: format of Data and pointer is merged into 16 Bits.

    Note3: 4096 is bigger then 12 bits - max value is 4095 (0 - 4095 = 4096 steps)

    Regards,
     Stefan
  • Ok codes are working fine and i can change the outpu but like very randomly i used I2C_write16(15,12);

    /* Initiate start and send first character */
     I2C_masterSendMultiByteStart(EUSCI_B3_BASE, (unsigned char)( ((writeByte>>8) & 0x0F) | ((pointer << 4) & 0x30) ) );
    
     I2C_masterSendMultiByteFinish(EUSCI_B3_BASE, (unsigned char)(writeByte & 0xFF));

    this makes me confused. i want to control output acording to my adc input so it is very hard with 2 variable(pointer and writebyte)

  • Note: pointer gives the PD value (PD0 and PD1) which can only be 0-3.
    Whereas writeByte gives the 12Bit DAC value (D0 -D 11) (0-4095) (changing the name would be good as this is not a byte).
    I recommend to study the DAC datasheet, esp. (DAC Register chapter in www.ti.com/.../dac121c085.pdf)

    Regards,
    Stefan
  • i did pd is 0 and writebyte is 400 but output is still 0
  • Just to ensure that should give 244mV.

    Above you mentioned: "Ok codes are working fine and i can change the outpu but like very randomly"
    Can you elaborate more on that: What voltage do you get? Is this stable or floating? Is there any correlation to the set value?

    Regards,
    Stefan
  • i think it gives so low voltage like 0.244mV or not at all. i thought it worked at first but now i sure i have no controll on it. just acts different when i change pd.
  • So what happens with
    I2C_write16(0x0, 4000);
    this should give a voltage of 2.44V

    What is different with change of PD?

    Regards,
    Stefan
  • it doesnt, if i make pd 1 or 2 output changes like 0.1mV thats it. if pd is 3 it acts like it is floating.

  • Can you confirm that the Vref_2.5V provides the 2.5V as reference voltage to the DAC and that this voltage is really there. I would just like to ensure that my assumtions based on your schematic or OK.

    Regards,
    Stefan

**Attention** This is a public forum