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.

Please help in understanding an i2c program

I try to use an example program i2c_master_rw_repeated_start-master_code.c, ti/mspware/MSPWare_2_30_00_49/driverlib/examples/MSP432P4xx/i2c/ in my app, but found it is not easy. Below is the code, into which I have inserted my questions in their places.

Please help, any answer will be appreciate greatly.

 

/******************************************************************************

* MSP432 I2C - EUSCI_B0_MODULE I2C Master TX bytes to MSP432 Slave - Repeated Start

*

* Description: This demo connects two MSP432 's via the I2C bus. The master

* transmits to the slave. This is the MASTER CODE. It continuously

* transmits an array of data and demonstrates how to implement an I2C

* master transmitter sending multiple bytes followed by a repeated start,

* followed by a read of multiple bytes. This is a common operation for

* reading register values from I2C slave devices such as sensors. The

* transaction for the I2C that is written looks as follows:

*

* ________________________________________________________________

* | Start   |     |     | Start   |                   |       |

* | 0x48Addr | 0x04 | 0x00 | 0x48Addr | <10 Byte Read>   | Stop |

* |   W     |     |     |   R     |                   |       |

* |__________|______|______|__________|___________________|_______|

*

* ACLK = n/a, MCLK = HSMCLK = SMCLK = BRCLK = default DCO = ~3.0MHz

*

*                               /|\ /|\

*               MSP432P401     10k 10k     MSP432P401

*                   slave         |   |         master

*             -----------------   |   |   -----------------

*           |     P1.6/UCB0SDA|<-|----+->|P1.6/UCB0SDA     |

*           |                 | |       |                 |

*           |                 | |       |                 |

*            |     P1.7/UCB0SCL|<-+------>|P1.7/UCB0SCL     |

*           |                 |         |                 |

*

* Author: Timothy Logan

*****************************************************************************/

/* DriverLib Defines */

#include "driverlib.h"

 

/* Standard Defines */

#include <stdint.h>

 

#include <stdbool.h>

#include <string.h>

 

/* Slave Address for I2C Slave */

#define SLAVE_ADDRESS       0x48

#define NUM_OF_REC_BYTES   10

 

/* Variables */

const uint8_t TXData[2] = {0x04, 0x00};

static uint8_t RXData[NUM_OF_REC_BYTES];

static volatile uint32_t xferIndex;

static volatile bool stopSent;

 

/* I2C Master Configuration Parameter */

const eUSCI_I2C_MasterConfig i2cConfig =

{

       EUSCI_B_I2C_CLOCKSOURCE_SMCLK,         // SMCLK Clock Source

       3000000,                               // SMCLK = 3MHz

       EUSCI_B_I2C_SET_DATA_RATE_100KBPS,     // Desired I2C Clock of 100khz

       0,                                     // No byte counter threshold

       EUSCI_B_I2C_NO_AUTO_STOP               // No Autostop

};

 

int main(void)

{

   volatile uint32_t ii;

 

   /* Disabling the Watchdog */

   MAP_WDT_A_holdTimer();

 

   /* Select Port 1 for I2C - Set Pin 6, 7 to input Primary Module Function,

     *   (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).

     */

   MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,

           GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

   stopSent = false;

   memset(RXData, 0x00, NUM_OF_REC_BYTES);

 

   /* Initializing I2C Master to SMCLK at 400kbs with no autostop */

   MAP_I2C_initMaster(EUSCI_B0_MODULE, &i2cConfig);

 

   /* Specify slave address */

   MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS);

 

   /* Set Master in transmit mode */

   MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_MODE);

 

   /* Enable I2C Module to start operations */

   MAP_I2C_enableModule(EUSCI_B0_MODULE);

 

   /* Enable and clear the interrupt flag */

   MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE,

           EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_RECEIVE_INTERRUPT0);

 

Q. 1: it should be Transmit interrupt

   //Enable master Receive interrupt

   MAP_I2C_enableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

   MAP_Interrupt_enableSleepOnIsrExit();

   MAP_Interrupt_enableInterrupt(INT_EUSCIB0);

 

   while (1)

   {

       /* Making sure the last transaction has been completely sent out */

       while (MAP_I2C_masterIsStopSent(EUSCI_B0_MODULE) == EUSCI_B_I2C_SENDING_STOP);

 

       /* Send start and the first byte of the transmit buffer. We have to send

         * two bytes to clean out whatever is in the buffer from a previous

* send */

Q. 2: Is this so called repeated start?

       MAP_I2C_masterSendMultiByteStart(EUSCI_B0_MODULE, TXData[0]);

       MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[0]);

 

Q. 3: done just a few lines early, why do it again? A waste or a must?

       /* Enabling transfer interrupt after stop has been sent */

       MAP_I2C_enableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

 

       /* While the stop condition hasn't been sent out... */

       while(!stopSent)

       {

           MAP_PCM_gotoLPM0InterruptSafe();

       }

 

       stopSent = false;

   }

}

 

/*******************************************************************************

* eUSCIB0 ISR. The repeated start and transmit/receive operations happen

* within this ISR.

*******************************************************************************/

void euscib0_isr(void)

{

   uint_fast16_t status;

 

   status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_MODULE);

   MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE, status);

Q. 4: It says it will change the mode, but didn’t do it.

   /* If we reached the transmit interrupt, it means we are at index 1 of

     * the transmit buffer. When doing a repeated start, before we reach the

     * last byte we will need to change the mode to receive mode, set the start

     * condition send bit, and then load the final byte into the TXBUF.

     */

   if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)

   {

       MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[1]);

       MAP_I2C_disableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

       MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_RECEIVE_MODE);

       xferIndex = 0;

       MAP_I2C_masterReceiveStart(EUSCI_B0_MODULE);

       MAP_I2C_enableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);

 

   }

 

   /* Receives bytes into the receive buffer. If we have received all bytes,

     * send a STOP condition */

   if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)

   {

       if(xferIndex == NUM_OF_REC_BYTES - 2) xferIndex = 8

       {

Q. 5: There is a byte still not received, why stop it?

           MAP_I2C_masterReceiveMultiByteStop(EUSCI_B0_MODULE);

Q. 6: It stoped already, why this line can be executed?

 

           RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_MODULE);

       }

       else if(xferIndex == NUM_OF_REC_BYTES - 1)

       {

           RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_MODULE);

           MAP_I2C_disableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);

Q. 7: will stop condition send in this mode set function?

           MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_MODE);

           xferIndex = 0;

           stopSent = true;

Q. 8: why disableSleepOnIsrExit() here

           MAP_Interrupt_disableSleepOnIsrExit();

       }

       else

       {  

           RXData[xferIndex++] =   MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_MODULE);

       }

 

   }

}

   

  • Hello Su Jin,

    1) You are correct, this comment should say Enable master Transmit interrupt. Please note that the receive interrupt is enabled/disabled inside of the eUSCIB0 ISR.
    2) Not a repeated start, one start followed by sending the first data byte. MAP_I2C_masterReceiveStart is the second start.
    3) This is a mistake, this line is only necessary once.
    4) It changes mode by disabling transmit interrupts, enabling receive interrupts, and sending a receive start command. Now the ISR will be interred as a receive interrupt to read data from the slave device.
    5) This is a preemptive command as the last byte will be stored into the receive buffer as we store the second-to-last byte, therefore the stop command is sent at this point.
    6) Same answer as #5, device registers such as the receive buffer can still be accessed and altered even after the stop command is sent.
    7) The stop condition has already been sent at the instance xferIndex == NUM_OF_REC_BYTES - 2 so it is not required here.
    8) This exits the MSP432 from LPM0 which was set using MAP_PCM_gotoLPM0InterruptSafe(), the CPU/instructions are now active after exiting the ISR and the variable stopSent is now true so the while(1) loop is allowed to start another iteration. The process then repeats itself.

    Regards,
    Ryan
  • Thank you very much.

    I almost understand the program now, but still little things need to be clarified.

    The first, question #2. My understanding now is: 

    MAP_I2C_masterSendMultiByteStart(EUSCI_B0_MODULE, TXData[0]);

             MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[0]);

    Despite the two functions have exactly the same parameters: EUSCI_B0_MODULE and TXData[0], but as you said 

    Ryan Brown1 said:
    one start followed by sending the first data byte
    , the start function does not send TXData[0], it use it as a pointer so it has to be there and can not be substituted. The second function actually does the sending. If we need to send more bytes we can do it like  

    MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[1]);

    MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[2]);

    ......

    MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[n]);

    Am I right?

    Q.4. I'm sorry I did not state the question clearly, below is the detailed statement of it. 

    The comments are

        /* If we reached the transmit interrupt, it means we are at index 1 of

         * the transmit buffer. When doing a repeated start, before we reach the

         * last byte we will need to change the mode to receive mode, set the start

         * condition send bit, and then load the final byte into the TXBUF.

         */

    According to it, the program lines should be

             MAP_I2C_disableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

             MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_RECEIVE_MODE);

    MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[1]);

    I.e. moving the MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[1]) down by two lines because it is the last byte, we have to do the change before it.

    With best wishes,

    Su 

  • Hello Su,

    Your understanding is correct for Q2. For Q4 if you set eUSCIB0 to receive mode then you will not be capable of transmitting TXData[1] beforehand, therefore MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[1]); comes first. The transmit ISR can be disabled at any time, it does not matter since we do not plan on using it again any time soon. I understand how the comments make this process confusing.

    Regards,
    Ryan
  • I try to understand more MSP432 example codes as more as possible to learn programming well. Below is another example code copied from ti/mspware/MSPWare_2_30_00_49/driverlib/examples/MSP432P4xx/i2c/i2c_master_w_multibyte_multislave_master.c, I think there are two bugs in it to that I have added comments wrriten in blue. After correction of these bugs I put a clear vesion of the program in the end, but I’m not sure if I’m right. Please check it out. Thank you very much.

    /* DriverLib Includes */

    #include "driverlib.h"

     

    /* Standard Includes */

    #include <stdint.h>

     

    #include <stdbool.h>

     

    /* Slave Address for I2C Slave */

    #define SLAVE_ADDRESS_1 0x48

    #define SLAVE_ADDRESS_2 0x49

     

    /* Statics */

    static uint8_t TXData = 0;

    static uint8_t TXByteCtr;

    static volatile bool sendStopCondition;

    static volatile bool sendToSlaveAddress2;

     

    /* I2C Master Configuration Parameter */

    const eUSCI_I2C_MasterConfig i2cConfig =

    {

           EUSCI_B_I2C_CLOCKSOURCE_SMCLK,         // SMCLK Clock Source

           3000000,                              // SMCLK = 3MHz

           EUSCI_B_I2C_SET_DATA_RATE_100KBPS,     // Desired I2C Clock of 100khz

           0,                                     // No byte counter threshold

           EUSCI_B_I2C_NO_AUTO_STOP               // No Autostop

    };

     

    int main(void)

    {

       volatile uint32_t ii;

     

       /* Disabling the Watchdog */

       MAP_WDT_A_holdTimer();

     

       /* Select Port 1 for I2C - Set Pin 6, 7 to input Primary Module Function,

         *   (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).

         */

       MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,

               GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

       sendStopCondition = false;

       sendToSlaveAddress2 = false;

     

       /* Initializing I2C Master to SMCLK at 400kbs with no autostop */

       MAP_I2C_initMaster(EUSCI_B0_MODULE, &i2cConfig);

     

       /* Specify slave address. For start we will do our first slave address */

       MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_1);

     

       /* Set Master in receive mode */

       MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_MODE);

     

       /* Enable I2C Module to start operations */

       MAP_I2C_enableModule(EUSCI_B0_MODULE);

     

       /* Enable and clear the interrupt flag */

       MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE,

               EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);

     

       //Enable master Receive interrupt

       MAP_I2C_enableInterrupt(EUSCI_B0_MODULE,

               EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);

       MAP_Interrupt_enableInterrupt(INT_EUSCIB0);

       

       while (1)

       {

     

           /* Load Byte Counter */

    Cooment #1: Every iteration reload the varable to 4, it will never goes to 0, so the master never has a chance to transmit data to slave 2

           TXByteCtr = 4;

     

           /* Making sure the last transaction has been completely sent out */

           while (MAP_I2C_masterIsStopSent(EUSCI_B0_MODULE) == EUSCI_B_I2C_SENDING_STOP);

     

           /* Sending the initial start condition for appropriate

             *   slave addresses */

           if(sendToSlaveAddress2)

           {

              MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_2);

           }

           else

           {

               MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_1);

           }

     

           MAP_I2C_masterSendMultiByteStart(EUSCI_B0_MODULE, TXData++);

     

          while(sendStopCondition == false)

           {

               /* Go to sleep while data is being transmitted */

               MAP_Interrupt_enableSleepOnIsrExit();

               MAP_PCM_gotoLPM0InterruptSafe();

           }

     

           sendStopCondition = false;

       }

    }

     

    /*******************************************************************************

    * The USCIAB0TX_ISR is structured such that it can be used to transmit any

    * number of bytes by pre-loading TXByteCtr with the byte count. Also, TXData

    * points to the next byte to transmit.

    *******************************************************************************/

    void euscib0_isr(void)

    {

       uint_fast16_t status;

     

       status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_MODULE);

       MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE, status);

     

       if (status & EUSCI_B_I2C_NAK_INTERRUPT)

       {

           MAP_I2C_masterSendStart(EUSCI_B0_MODULE);

           return;

       }

     

       if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)

       {

           MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_1);

       }

    Comment #2: EUSCI_B_I2C_TRANSMIT_INTERRUPT1 is not enabled yet.

       if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT1)

       {

           MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_2);

       }

     

       /* Check the byte counter */

       if (TXByteCtr)

       {

           /* Send the next data and decrement the byte counter */

           MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData++);

           TXByteCtr--;

       }

       else

       {

           MAP_I2C_masterSendMultiByteStop(EUSCI_B0_MODULE);

          sendStopCondition = true;

           sendToSlaveAddress2 = !sendToSlaveAddress2;

           MAP_Interrupt_disableSleepOnIsrExit();

       }

     

    }

     

     


    /* Slave Address for I2C Slave */

    #define SLAVE_ADDRESS_1 0x48

    #define SLAVE_ADDRESS_2 0x49

     

    /* Statics */

    static uint8_t TXData = 0;

    static uint8_t TXByteCtr;

    static volatile bool sendStopCondition;

    static volatile bool sendToSlaveAddress2;

     

    /* I2C Master Configuration Parameter */

    const eUSCI_I2C_MasterConfig i2cConfig =

    {

           EUSCI_B_I2C_CLOCKSOURCE_SMCLK,        // SMCLK Clock Source

           3000000,                               // SMCLK = 3MHz

           EUSCI_B_I2C_SET_DATA_RATE_100KBPS,     // Desired I2C Clock of 100khz

           0,                                     // No byte counter threshold

           EUSCI_B_I2C_NO_AUTO_STOP               // No Autostop

    };

     

    int main(void)

    {

       volatile uint32_t ii;

     

       /* Disabling the Watchdog */

       MAP_WDT_A_holdTimer();

     

       /* Select Port 1 for I2C - Set Pin 6, 7 to input Primary Module Function,

         *   (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).

         */

       MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,

               GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

       sendStopCondition = false;

       sendToSlaveAddress2 = false;

     

       /* Initializing I2C Master to SMCLK at 400kbs with no autostop */

       MAP_I2C_initMaster(EUSCI_B0_MODULE, &i2cConfig);

     

       /* Specify slave address. For start we will do our first slave address */

       MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_1);

     

       /* Set Master in receive mode */

       MAP_I2C_setMode(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_MODE);

     

       /* Enable I2C Module to start operations */

       MAP_I2C_enableModule(EUSCI_B0_MODULE);

     

       //Clear the interrupt flags

       MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE,

               EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);

     

       //Enable the interrupts

       MAP_I2C_enableInterrupt(EUSCI_B0_MODULE,

               EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);

       MAP_Interrupt_enableInterrupt(INT_EUSCIB0);

       

       TXByteCtr = 4;

       while (1)

       {

           /* Making sure the last transaction has been completely sent out */

           while (MAP_I2C_masterIsStopSent(EUSCI_B0_MODULE) == EUSCI_B_I2C_SENDING_STOP);

     

           /* Sending the initial start condition for appropriate

             *   slave addresses */

           if(sendToSlaveAddress2)

           {

               MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_2);

     

    //Clear the interrupt flags

    MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE,

    EUSCI_B_I2C_TRANSMIT_INTERRUPT1 + EUSCI_B_I2C_NAK_INTERRUPT);

    //enable the interrupts

    MAP_I2C_enableInterrupt(EUSCI_B0_MODULE,

    EUSCI_B_I2C_TRANSMIT_INTERRUPT1 + EUSCI_B_I2C_NAK_INTERRUPT);

    //enable INT_EUSCIB0 interrupt

       MAP_Interrupt_enableInterrupt(INT_EUSCIB0);

           }

     

           MAP_I2C_masterSendMultiByteStart(EUSCI_B0_MODULE, TXData++);

     

           while(sendStopCondition == false)

           {

               /* Go to sleep while data is being transmitted */

               MAP_Interrupt_enableSleepOnIsrExit();

               MAP_PCM_gotoLPM0InterruptSafe();

           }

    //both slaves received data already, break the interation

    ifTXByteCtr==0 & sendToSlaveAddress2) return(0);

           sendStopCondition = false;

       }

    }

     

    /*******************************************************************************

    * The USCIAB0TX_ISR is structured such that it can be used to transmit any

    * number of bytes by pre-loading TXByteCtr with the byte count. Also, TXData

    * points to the next byte to transmit.

    *******************************************************************************/

    void euscib0_isr(void)

    {

       uint_fast16_t status;

     

       status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_MODULE);

       MAP_I2C_clearInterruptFlag(EUSCI_B0_MODULE, status);

     

       if (status & EUSCI_B_I2C_NAK_INTERRUPT)

       {

           MAP_I2C_masterSendStart(EUSCI_B0_MODULE);

           return;

       }

     

         /* Check the byte counter */

       if (TXByteCtr)

       {

           /* Send the next data and decrement the byte counter */

           MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData++);

           TXByteCtr--;

       }

       else

       {

           MAP_I2C_masterSendMultiByteStop(EUSCI_B0_MODULE);

    //disable the interrups

           MAP_I2C_disableInterrupt(EUSCI_B0_MODULE,

    EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_NAK_INTERRUPT);

     

           sendStopCondition = true;

           sendToSlaveAddress2 = !sendToSlaveAddress2;

    //set TXByteCtr

           TXByteCtr = 4;        

           MAP_Interrupt_disableSleepOnIsrExit();

       }

     

    }

  • 1) TXByteCtr is decremented in the eUSCIB0 ISR which does not exit LPM and continue CPU operation until the TXByteCtr has been fully decremented, in which case the sendToSlaveAddress2 boolean value is inversed and communication with the next slave address begins with the next iteration of the while(1) loop.

    2) EUSCI_B_I2C_TRANSMIT_INTERRUPT1 is not necessary since we are not using the eUSCIB1 peripheral.

    Regards,
    Ryan
  • 1) Yes, you are right.

    2) I got confused.

    Ryan Brown1 said:
    EUSCI_B_I2C_TRANSMIT_INTERRUPT1 is not necessary since we are not using the eUSCIB1 peripheral

    But eUSCIB0 ISR use it, below are the lines:

     if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT1)
        {
            MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_2);
        }

    Also you mean all interrupts generated by every peripheral using eUSCIB0 will trigger EUSCI_B_I2C_TRANSMIT_INTERRUPT0. Is my understanding right? 

    I thought slave #1 triggers EUSCI_B_I2C_TRANSMIT_INTERRUPT0, slave #2 triggers USCI_B_I2C_TRANSMIT_INTERRUPT1. So I was wrong.

  • The slaves are multiplexed on the same I2C lines and use the same eUSCIB0 peripheral. They therefore both use EUSCI_B_I2C_TRANSMIT_INTERRUPT0 so the line that includes EUSCI_B_I2C_TRANSMIT_INTERRUPT1 appears to be a mistake, as eUSCIB1 is never initialized or used elsewhere in the code.

    Regards,
    Ryan
  • Then there may have a problem if more than slaves use the same eUSCIB0 peripheral, i.e. how does the master know which is the source of an interrupt?
    Thank you very much.
    Su

  • Because of the unique slave address sent following the start condition. The line MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS_X); will determine which slave device listens & responds to the master's commands. The other will remain dormant.

    Regards,
    Ryan
  • Thanks Ryan and Su!  I found this very useful.  Hopefully these mistakes get fixed in driverlib on the next release.

    Rob

  • Hello,
    How can I verify the above example code?
    Is I2C Interface peripheral is necessary? Or we can verify the clk and data in DCO?

    Thank You
  • Hello Kranthi,

    You can verify the example code without a slave device by pulling up the SDA and SCL lines with 10 kOhm pull-up resistors and monitoring the lines with an oscilloscope or logic analyzer.

    Regards,
    Ryan
  • Hello Ryan,

    Thank you for your reply,
    I've connected the 10kOhm pullup resistors to sda and scl pins but i did'nt get the clock in oscilloscope.
    But I observed in registers that the data is stored in Txd buffer, but I am not getting SCL in oscilloscope why?

    Thank You Ryan
  • Hello Ryan,

    Thank you, I've got the scl and sda and also I've seen sda and scl on Oscillator also.

    Thank you once again
  • Hello Ryan,
    I got only the slave address in sda line, I didn't get the transmitted data on sda, why?
    Thank You
  • Kranthi,

    This depends on your code setup, type of slave device used, and what commands you are using to attempt data transmission. Seeing the slave data sent on the SDA line at least confirms initialization of the I2C. Could the slave device be holding the line after receiving the address?

    Regards,
    Ryan
  • Thanks Ryan and Su, that was really helpful.

    I noticed a small mistake which can be easily corrected. In fact, Su had already asked in the 3rd question

    Su Jin said:

     

     

    Q. 3: done just a few lines early, why do it again? A waste or a must?

           /* Enabling transfer interrupt after stop has been sent */

           MAP_I2C_enableInterrupt(EUSCI_B0_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

     



    After Ryan's answer I thought it shouldn't cause any problem if I simply delete one of these lines and I deleted the second one. What I saw was a correct reading in the first loop of the while(1) but after that all the readings were wrong. It took 30 minutes to find the problem (smaller the problem, harder to find). The problem is that the transmit interrupt isn't enabled again after the reading is done. The line enabling it comes after sending the first byte in the while loop. Therefore, it works when transmit interrupt is already enabled before going into the while loop but it does not work anymore as it is disabled later on. Either you should enable it again at the end of reading or you can simply change the position of the specific line as below. By doing so, in the beginning of the while loop it is going to be enabled before sending the TXData.

     while (1)
        {
    
        	//Enable master Transmit interrupt
        	MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
    
            /* Making sure the last transaction has been completely sent out */
            while (MAP_I2C_masterIsStopSent(EUSCI_B0_BASE) == EUSCI_B_I2C_SENDING_STOP);
            while (MAP_I2C_isBusBusy(EUSCI_B0_BASE) == EUSCI_B_I2C_BUS_BUSY);
    
            /* Send start and the first byte of the transmit buffer. We have to send
             * two bytes to clean out whatever is in the buffer from a previous
             * send  */
            MAP_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, TXData);
            MAP_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, TXData);
    
    ....


    By the way, I have only one byte of TXData. That's why I changed the notation, it has nothing to do with the problem.

**Attention** This is a public forum