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.

MSP432 LCD I2C communication stops

Other Parts Discussed in Thread: MIDAS

Hi everyone,


I am trying to get a Midas 20x4 LCD Display to work over I2C, until now without success. After several fruitless attempts of writing a library for the LCD, all I am trying to achieve now is powering the module up. To this point I have not seen any sign of life on the display itself which makes me doubt that it is still OK, so it might just be broken.

The only life sign i get is what I think is an Acknowledge after sending some data. The Display needs a control byte after the address which defines if the following information is a command or display data.

The picture shows what i captured with an oscilloscope. The MSP432 sends the address (0x3c) which gets acknowledged. The next byte is just 0x00 ( the control byte for a command) which gets acknowledged too.  The next byte is the command 0x3A (as advised in the datasheet of the LCD). Then the communication suddenly stops and restarts while transmitting the next byte.

The LCD has 13 pins which are connected as mentioned on page 7 in the datasheet http://www.farnell.com/datasheets/1663648.pdf

This is my first attempt in using I2C so I am not experienced enough to see why this is happening and if my code is correct. I would appreciate if you could have a look on the code (which is modified from a driverlib example).

/* DriverLib Includes */
#include "driverlib.h"

/* Standard Includes */
#include <stdint.h>

#include <stdbool.h>

/* Slave Address for I2C Slave */
#define SLAVE_ADDRESS 0x3c

/* Statics */
static uint8_t TXData[10] = {0x00, 0x3A, 0x1E, 0x39, 0x1C, 0x79, 0x5D, 0x6C, 0x0C, 0x01};
static uint8_t TXByteCtr = 1;
static uint8_t sent = 0;

/* 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();

    P1DIR |= BIT0;
    P1OUT &= ~(BIT0);
    P3DIR |= BIT7;

    /* 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);

    /* Initializing I2C Master to SMCLK at 100kbs with no autostop */
    MAP_I2C_initMaster(EUSCI_B0_MODULE, &i2cConfig);

    /* Specify slave address */
    MAP_I2C_setSlaveAddress(EUSCI_B0_MODULE, SLAVE_ADDRESS);

    /* 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);
    


    uint32_t i;

    P3OUT &= ~(BIT7);
    //for(i=0;i<36000;i++);	//Delay > 10ms.
    P3OUT |= BIT7;
    //for(i=0;i<3000;i++);	//Delay > 1ms

    while (1)
    {
         //Delay between Transmissions
        //for (ii = 0; ii < 4000; ii++);

        // 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
        MAP_I2C_masterSendMultiByteStart(EUSCI_B0_MODULE, TXData[0]);

        MAP_Interrupt_enableSleepOnIsrExit();
        MAP_PCM_gotoLPM0InterruptSafe();

    }
}

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);
        P1OUT |= BIT0;
    }

    if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
    {
        // Check the byte counter
        if (!sent)
        {
            // Send the next data and decrement the byte counter
            MAP_I2C_masterSendMultiByteNext(EUSCI_B0_MODULE, TXData[TXByteCtr]);
            sent = 1;
        } else
        {
            MAP_I2C_masterSendMultiByteStop(EUSCI_B0_MODULE);
            MAP_Interrupt_disableSleepOnIsrExit();
            TXByteCtr++;
            sent = 0;
        }
    }
    if (TXByteCtr > 10)
    {
    	MAP_Interrupt_disableInterrupt(INT_EUSCIB0);
    }

}

The acknowledge of the LCD did send is the only reason I have to hope that the display is still working. Sadly, it did never light up or show me anything.


Would be nice if somebody gave the code a look.

Jonathan

  • After a second look I know now that the communication stops because there is a stopcondition created after every transmitted command. I am still not shure if all the commands get sent and the display doesnt light up, so if you check if the code is correct that would help me. Thanks in advance.

    Jonathan
  • Hi Jonathan,

     Attached is the i2c driver that I have been using for sometime.

    i2c_driver.c

    i2c_driver.h

    Please give this a try and let us know if it corrected your problem. Please run " initI2C();" after you've initialized your system clocks, and the you can call writeI2C or readI2C.

    For example:

    #define OPT3001_I2C_ADDRESS             0x47
    
    #define REGISTER_LENGTH                 2
    
    #define REG_RESULT                      0x00
    #define REG_CONFIGURATION               0x01
    
    uint16_t val;
    
    writeI2C(OPT3001_I2C_ADDRESS, REG_CONFIGURATION, (uint8_t*)&val, REGISTER_LENGTH);
    readI2C(OPT3001_I2C_ADDRESS, REG_RESULT, (uint8_t *)&val, REGISTER_LENGTH); 

    Regards,

     David

  • Did the code example fix your problem? If not please let us know, otherwise, we will close this thread (you can reopen it later if needed).

  • Hi David,

    To send data through your writeI2C command, do I set 'val' just beforehand? i.e.:

    val = 0x08;
    writeI2C(SLAVE_ADDR, REG_ADDR, (uint8_t*)&val, REGISTER_LENGTH);
  • Hi!

    Sorry for the late answer, I didnt check. I'll look into the driver and will give feedback soon.

    Thanks

    Jonathan

  • I'm marking the thread closed due to inactivity, but you can always use "reject answer" or simply post back to re-open it if you need more help on this issue.
  • Ok, my conclusion on your driver, per what bus pirate monitoring shows, is your revised driver can't read because it doesn't do a proper handshake.
    [ -> start bit
    + -> ack
    ] stop bit
    0xd2 -> write address
    0xd3 -> read address

    This is what bus pirate shows is going on:

    [0xD2+0x00+[0xD3+0x00+0x00+]

    This is, I think, what it should be: [0xD2+0x00+0xD3+0x00+0x00+]

    This is what I got the original driver to do, write followed by read 32 bytes:

    [0xD2+0x00-0xD3+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x07-0xEF-0xDF-0x80+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x1F-0xBC+0x00+0x00+0x10+]]

    The problem with the original driver is I can't do a write after a single byte read.
    I can read 2, 4, ..32 bytes no problem, but if I do a read 1 byte, the next write locks up waiting for tx interrupt.
    ----
    Should I open this up as a problem, or can you take it from here?
    ---
  • Another thing to be careful of is the driver coding while loops on status without also having timeouts in the loop.
    These have a tendency to, when the status never comes true, lock up the code.
  • David, thank you so much for providing this VERY useful driver. I can not tell you how much frustration you have saved me!

    I have modified the driver slightly with updated EUSCI_Bx_BASE instead of EUSCI_Bx_MODULE and put modules in each function call so that multiple I2C modules can be used in a program. Updated code is attached below.

    //*****************************************************************************
    //
    // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //  Redistributions of source code must retain the above copyright
    //  notice, this list of conditions and the following disclaimer.
    //
    //  Redistributions in binary form must reproduce the above copyright
    //  notice, this list of conditions and the following disclaimer in the
    //  documentation and/or other materials provided with the
    //  distribution.
    //
    //  Neither the name of Texas Instruments Incorporated nor the names of
    //  its contributors may be used to endorse or promote products derived
    //  from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    //****************************************************************************
    
    //************************MODIFICATON INFORMATION*****************************
    //Modified from original source located at:
    // https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/472504/1701554#1701554
    //
    //Modified by Reid Kersey, CEO, Sniffer GPS - 6/7/2017
    //  sniffergps.com
    //  reid@sniffergps.com
    //  678-209-2215
    //
    //Updates:
    //Changed EUSCI_Bx_MODULE to EUSCI_Bx_BASE
    //Changed from using B1 to allowing use of any Bx Module
    //Added function description comments
    
    //Feel free to contact me about modifications to this code or questions about usage,
    //however I am not the original author. Credit goes to DavidL https://e2e.ti.com/members/2005340
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "msp432.h"
    #include "i2c_driver.h"
    #include "driverlib.h"
    
    //*****************************************************************************
    //
    // Definitions
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Global Data
    //
    //*****************************************************************************
    volatile eUSCI_status ui8Status;
    
    uint8_t  *pData;
    uint8_t  ui8DummyRead;
    uint32_t g_ui32ByteCount;
    bool     burstMode = false;
    
    
    //B0-3 configurations
    /* I2C Master Configuration Parameter */
    volatile eUSCI_I2C_MasterConfig i2cConfig_B0 =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            0,
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    
    volatile eUSCI_I2C_MasterConfig i2cConfig_B1 =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            0,
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    
    volatile eUSCI_I2C_MasterConfig i2cConfig_B2 =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            0,
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    
    volatile eUSCI_I2C_MasterConfig i2cConfig_B3 =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            0,
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    
    //*****************************************************************************
    //
    // Imported Data
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Constants
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Function Prototypes
    //
    //*****************************************************************************
    
    /***********************************************************
      Function:
    
      You MUST call this before doing any read or writes
        @param module the EUSCI module to use ex: EUSCI_B0_BASE
    */
    void initI2C(int module)
    {
        /* I2C Clock Soruce Speed */
        if(module == EUSCI_B0_BASE){
            i2cConfig_B0.i2cClk = MAP_CS_getSMCLK();
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN6 | GPIO_PIN7,
                    GPIO_PRIMARY_MODULE_FUNCTION);
    
            /* Initializing I2C Master to SMCLK at 100kbs with autostop */
            MAP_I2C_initMaster(EUSCI_B0_BASE, &i2cConfig_B0);
        }else if(module == EUSCI_B1_BASE){
            i2cConfig_B1.i2cClk = MAP_CS_getSMCLK();
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN5 | GPIO_PIN4,
                    GPIO_PRIMARY_MODULE_FUNCTION);
    
            /* Initializing I2C Master to SMCLK at 100kbs with autostop */
            MAP_I2C_initMaster(EUSCI_B1_BASE, &i2cConfig_B1);
        }else if(module == EUSCI_B2_BASE){
            i2cConfig_B1.i2cClk = MAP_CS_getSMCLK();
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN6 | GPIO_PIN7,
                    GPIO_PRIMARY_MODULE_FUNCTION);
    
            /* Initializing I2C Master to SMCLK at 100kbs with autostop */
            MAP_I2C_initMaster(EUSCI_B2_BASE, &i2cConfig_B2);
        }else if(module == EUSCI_B3_BASE){
            i2cConfig_B1.i2cClk = MAP_CS_getSMCLK();
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN6 | GPIO_PIN7,
                    GPIO_SECONDARY_MODULE_FUNCTION);
    
            /* Initializing I2C Master to SMCLK at 100kbs with autostop */
            MAP_I2C_initMaster(EUSCI_B3_BASE, &i2cConfig_B3);
        }
    }
    
    /***********************************************************
      Function:
    
      @param module the EUSCI module to use ex: EUSCI_B0_BASE
      @param ui8Addr the 7 bit address of the module
      @param ui8Reg the register to write to
      @param Data a pointer to where the data to be written is stored
      @param ui32ByteCount the number of bytes to write
      @returns true if successful, false otherwise
    */
    bool writeI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
    {
        /* Wait until ready to write */
        while (MAP_I2C_isBusBusy(module));
    
        /* Assign Data to local Pointer */
        pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(module);
    
        /* Setup the number of bytes to transmit + 1 to account for the register byte */
        if(module == EUSCI_B0_BASE){
            i2cConfig_B0.byteCounterThreshold = ui8ByteCount + 1;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0);
        }else if(module == EUSCI_B1_BASE){
            i2cConfig_B1.byteCounterThreshold = ui8ByteCount + 1;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1);
        }else if(module == EUSCI_B2_BASE){
            i2cConfig_B2.byteCounterThreshold = ui8ByteCount + 1;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2);
        }else if(module == EUSCI_B3_BASE){
            i2cConfig_B3.byteCounterThreshold = ui8ByteCount + 1;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3);
        }else{
            return false;
        }
    
    
        /* Load device slave address */
        MAP_I2C_setSlaveAddress(module, ui8Addr);
    
        /* Enable I2C Module to start operations */
        MAP_I2C_enableModule(module);
    
        /* Enable master STOP, TX and NACK interrupts */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
        /* Set our local state to Busy */
        ui8Status = eUSCI_BUSY;
    
        /* Send start bit and register */
        MAP_I2C_masterSendMultiByteStart(module,ui8Reg);
    
        /* Enable master interrupt for the remaining data */
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        // NOW WAIT FOR DATA BYTES TO BE SENT
        while(ui8Status == eUSCI_BUSY)
        {
    #ifdef USE_LPM
            MAP_PCM_gotoLPM0();
    #else
            __no_operation();
    #endif
        }
    
        /* Disable interrupts */
        MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        if(ui8Status == eUSCI_NACK)
        {
            return(false);
        }
        else
        {
            return(true);
        }
    }
    
    /***********************************************************
      Function:
    
      @param module the EUSCI module to use ex: EUSCI_B0_BASE
      @param ui8Addr the 7 bit address of the module
      @param ui8Reg the register to read from
      @param Data a pointer to where to put the data
      @param ui32ByteCount the number of bytes to read
      @returns true if successful, false otherwise
    */
    bool readI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
    {
        /* Todo: Put a delay */
        /* Wait until ready */
        while (MAP_I2C_isBusBusy(module));
    
        /* Assign Data to local Pointer */
        pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(module);
    
        /* Setup the number of bytes to receive */
        if(module == EUSCI_B0_BASE){
            i2cConfig_B0.byteCounterThreshold = ui8ByteCount;
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0);
        }else if(module == EUSCI_B1_BASE){
            i2cConfig_B1.byteCounterThreshold = ui8ByteCount;
            i2cConfig_B1.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1);
        }else if(module == EUSCI_B2_BASE){
            i2cConfig_B2.byteCounterThreshold = ui8ByteCount;
            i2cConfig_B2.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2);
        }else if(module == EUSCI_B3_BASE){
            i2cConfig_B3.byteCounterThreshold = ui8ByteCount;
            i2cConfig_B3.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3);
        }else{
            return false;
        }
    
        /* Load device slave address */
        MAP_I2C_setSlaveAddress(module, ui8Addr);
    
        /* Enable I2C Module to start operations */
        MAP_I2C_enableModule(module);
    
        /* Enable master STOP and NACK interrupts */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT);
    
        /* Set our local state to Busy */
        ui8Status = eUSCI_BUSY;
    
        /* Send start bit and register */
        MAP_I2C_masterSendMultiByteStart(module,ui8Reg);
    
        /* Enable master interrupt for the remaining data */
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        /* NOTE: If the number of bytes to receive = 1, then as target register is being shifted
         * out during the write phase, UCBxTBCNT will be counted and will trigger STOP bit prematurely
         * If count is > 1, wait for the next TXBUF empty interrupt (just after reg value has been
         * shifted out
         *
         * If your code is getting stuck here, you probably called this function from an interrupt
         * DON'T DO THAT!
         */
        while(ui8Status == eUSCI_BUSY)
        {
            if(MAP_I2C_getInterruptStatus(module, EUSCI_B_I2C_TRANSMIT_INTERRUPT0))
            {
                ui8Status = eUSCI_IDLE;
            }
        }
    
        ui8Status = eUSCI_BUSY;
    
        /* Turn off TX and generate RE-Start */
        MAP_I2C_masterReceiveStart(module);
    
        /* Enable RX interrupt */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    
        /* Wait for all data be received */
        while(ui8Status == eUSCI_BUSY)
        {
    
    #ifdef USE_LPM
            MAP_PCM_gotoLPM0();
    #else
            __no_operation();
    #endif
        }
    
        /* Disable interrupts */
        MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        if(ui8Status == eUSCI_NACK)
        {
            return(false);
        }
        else
        {
            return(true);
        }
    }
    
    /***********************************************************
      Function:
      @param module the EUSCI module to use ex: EUSCI_B0_BASE
      @param ui8Addr the 7 bit address of the module
      @param ui8Reg the register to read from
      @param Data a pointer to where to put the data
      @param ui32ByteCount the number of bytes to read
      @returns true if successful, false otherwise
    */
    bool readBurstI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint32_t ui32ByteCount)
    {
        /* Todo: Put a delay */
        /* Wait until ready */
        while (MAP_I2C_isBusBusy(module));
    
        /* Assign Data to local Pointer */
        pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(module);
    
        /* Setup the number of bytes to receive */
        if(module == EUSCI_B0_BASE){
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
            g_ui32ByteCount = ui32ByteCount;
            burstMode = true;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0);
        }else if(module == EUSCI_B1_BASE){
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
            g_ui32ByteCount = ui32ByteCount;
            burstMode = true;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1);
        }else if(module == EUSCI_B2_BASE){
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
            g_ui32ByteCount = ui32ByteCount;
            burstMode = true;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2);
        }else if(module == EUSCI_B3_BASE){
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
            g_ui32ByteCount = ui32ByteCount;
            burstMode = true;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3);
        }else{
            return false;
        }
    
    
        /* Load device slave address */
        MAP_I2C_setSlaveAddress(module, ui8Addr);
    
        /* Enable I2C Module to start operations */
        MAP_I2C_enableModule(module);
    
        /* Enable master STOP and NACK interrupts */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT);
    
        /* Set our local state to Busy */
        ui8Status = eUSCI_BUSY;
    
        /* Send start bit and register */
        MAP_I2C_masterSendMultiByteStart(module,ui8Reg);
    
        /* Enable master interrupt for the remaining data */
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        /* NOTE: If the number of bytes to receive = 1, then as target register is being shifted
         * out during the write phase, UCBxTBCNT will be counted and will trigger STOP bit prematurely
         * If count is > 1, wait for the next TXBUF empty interrupt (just after reg value has been
         * shifted out
         *
         * If your code is getting stuck here, you probably called this function from an interrupt
         * DON'T DO THAT!
         */
        while(ui8Status == eUSCI_BUSY)
        {
            if(MAP_I2C_getInterruptStatus(module, EUSCI_B_I2C_TRANSMIT_INTERRUPT0))
            {
                ui8Status = eUSCI_IDLE;
            }
        }
    
        ui8Status = eUSCI_BUSY;
    
        /* Turn off TX and generate RE-Start */
        MAP_I2C_masterReceiveStart(module);
    
        /* Enable RX interrupt */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    
        /* Wait for all data be received */
        while(ui8Status == eUSCI_BUSY)
        {
    
    #ifdef USE_LPM
            MAP_PCM_gotoLPM0();
    #else
            __no_operation();
    #endif
        }
    
        /* Disable interrupts */
        MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
    
        if(ui8Status == eUSCI_NACK)
        {
            return(false);
        }
        else
        {
            return(true);
        }
    }
    
    /***********************************************************
      Function: euscib0IntHandler
     */
    void eusciB0IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_BASE);
        MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
            /* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
    
            /* Clear any pending TX interrupts */
            MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
            /* Set our local state to NACK received */
            ui8Status = eUSCI_NACK;
        }
    
        if (status & EUSCI_B_I2C_START_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_START;
        }
    
        if (status & EUSCI_B_I2C_STOP_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_STOP;
        }
    
        if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
        {
            /* RX data */
            *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
            ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
    
            if (burstMode)
            {
                g_ui32ByteCount--;
                if (g_ui32ByteCount == 1)
                {
                    burstMode = false;
    
                    /* Generate STOP */
                    MAP_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
                }
            }
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
            /* Send the next data */
            MAP_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    void eusciB1IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B1_BASE);
        MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
            /* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);
    
            /* Clear any pending TX interrupts */
            MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
            /* Set our local state to NACK received */
            ui8Status = eUSCI_NACK;
        }
    
        if (status & EUSCI_B_I2C_START_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_START;
        }
    
        if (status & EUSCI_B_I2C_STOP_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_STOP;
        }
    
        if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
        {
            /* RX data */
            *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
            ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
    
            if (burstMode)
            {
                g_ui32ByteCount--;
                if (g_ui32ByteCount == 1)
                {
                    burstMode = false;
    
                    /* Generate STOP */
                    MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);
                }
            }
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
            /* Send the next data */
            MAP_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    void eusciB2IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B2_BASE);
        MAP_I2C_clearInterruptFlag(EUSCI_B2_BASE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
            /* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B2_BASE);
    
            /* Clear any pending TX interrupts */
            MAP_I2C_clearInterruptFlag(EUSCI_B2_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
            /* Set our local state to NACK received */
            ui8Status = eUSCI_NACK;
        }
    
        if (status & EUSCI_B_I2C_START_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_START;
        }
    
        if (status & EUSCI_B_I2C_STOP_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_STOP;
        }
    
        if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
        {
            /* RX data */
            *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE);
            ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE);
    
            if (burstMode)
            {
                g_ui32ByteCount--;
                if (g_ui32ByteCount == 1)
                {
                    burstMode = false;
    
                    /* Generate STOP */
                    MAP_I2C_masterSendMultiByteStop(EUSCI_B2_BASE);
                }
            }
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
            /* Send the next data */
            MAP_I2C_masterSendMultiByteNext(EUSCI_B2_BASE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    void eusciB3IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B3_BASE);
        MAP_I2C_clearInterruptFlag(EUSCI_B3_BASE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
            /* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B3_BASE);
    
            /* Clear any pending TX interrupts */
            MAP_I2C_clearInterruptFlag(EUSCI_B3_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
            /* Set our local state to NACK received */
            ui8Status = eUSCI_NACK;
        }
    
        if (status & EUSCI_B_I2C_START_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_START;
        }
    
        if (status & EUSCI_B_I2C_STOP_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_STOP;
        }
    
        if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
        {
            /* RX data */
            *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B3_BASE);
            ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B3_BASE);
    
            if (burstMode)
            {
                g_ui32ByteCount--;
                if (g_ui32ByteCount == 1)
                {
                    burstMode = false;
    
                    /* Generate STOP */
                    MAP_I2C_masterSendMultiByteStop(EUSCI_B3_BASE);
                }
            }
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
            /* Send the next data */
            MAP_I2C_masterSendMultiByteNext(EUSCI_B3_BASE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    

    6622.i2c_driver.h

  • Updated code: removed slow speed bug on I2C B2 and B3 lines

    //*****************************************************************************
    //
    // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions
    // are met:
    //
    //  Redistributions of source code must retain the above copyright
    //  notice, this list of conditions and the following disclaimer.
    //
    //  Redistributions in binary form must reproduce the above copyright
    //  notice, this list of conditions and the following disclaimer in the
    //  documentation and/or other materials provided with the
    //  distribution.
    //
    //  Neither the name of Texas Instruments Incorporated nor the names of
    //  its contributors may be used to endorse or promote products derived
    //  from this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    //
    //****************************************************************************
    
    //************************MODIFICATON INFORMATION*****************************
    //Modified from original source located at:
    // https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/472504/1701554#1701554
    //
    //Modifed by Reid Kersey, CEO, Sniffer GPS - 7/19/2017
    //  sniffergps.com
    //  reid@sniffergps.com
    //  678-209-2215
    //
    //Updates:
    //6/7/2017
    //Changed EUSCI_Bx_MODULE to EUSCI_Bx_BASE
    //Changed from using B1 to allowing use of any Bx Module
    //Added funciton description comments
    
    //7/19/2017
    //removed slow speed bug on B2 and B3
    
    //Feel free to contact me about modifications to this code or questions about usage,
    //however I am not the original author. Credit goes to DavidL https://e2e.ti.com/members/2005340
    
    #include <stdbool.h>
    #include <stdint.h>
    #include "msp432.h"
    #include "i2c_driver.h"
    #include "driverlib.h"
    
    //*****************************************************************************
    //
    // Definitions
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Global Data
    //
    //*****************************************************************************
    volatile eUSCI_status ui8Status;
    
    uint8_t  *pData;
    uint8_t  ui8DummyRead;
    uint32_t g_ui32ByteCount;
    bool     burstMode = false;
    
    
    //B0-3 configurations
    /* I2C Master Configuration Parameter */
    volatile eUSCI_I2C_MasterConfig i2cConfig_B0 =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            0,
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    
    volatile eUSCI_I2C_MasterConfig i2cConfig_B1 =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            0,
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    
    volatile eUSCI_I2C_MasterConfig i2cConfig_B2 =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            0,
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    
    volatile eUSCI_I2C_MasterConfig i2cConfig_B3 =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
            0,
            EUSCI_B_I2C_SET_DATA_RATE_100KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    
    //*****************************************************************************
    //
    // Imported Data
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Constants
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Function Prototypes
    //
    //*****************************************************************************
    
    /***********************************************************
      Function:
    
      You MUST call this before doing any read or writes
        @param module the EUSCI module to use ex: EUSCI_B0_BASE
    */
    void initI2C(int module)
    {
        /* I2C Clock Soruce Speed */
        if(module == EUSCI_B0_BASE){
            i2cConfig_B0.i2cClk = MAP_CS_getSMCLK();
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN6 | GPIO_PIN7,
                    GPIO_PRIMARY_MODULE_FUNCTION);
    
            /* Initializing I2C Master to SMCLK at 100kbs with autostop */
            MAP_I2C_initMaster(EUSCI_B0_BASE, &i2cConfig_B0);
        }else if(module == EUSCI_B1_BASE){
            i2cConfig_B1.i2cClk = MAP_CS_getSMCLK();
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN5 | GPIO_PIN4,
                    GPIO_PRIMARY_MODULE_FUNCTION);
    
            /* Initializing I2C Master to SMCLK at 100kbs with autostop */
            MAP_I2C_initMaster(EUSCI_B1_BASE, &i2cConfig_B1);
        }else if(module == EUSCI_B2_BASE){
            i2cConfig_B2.i2cClk = MAP_CS_getSMCLK();
    
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN6 | GPIO_PIN7,
                    GPIO_PRIMARY_MODULE_FUNCTION);
    
            /* Initializing I2C Master to SMCLK at 100kbs with autostop */
            MAP_I2C_initMaster(EUSCI_B2_BASE, &i2cConfig_B2);
        }else if(module == EUSCI_B3_BASE){
            i2cConfig_B3.i2cClk = MAP_CS_getSMCLK();
            GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN6 | GPIO_PIN7,
                    GPIO_SECONDARY_MODULE_FUNCTION);
    
            /* Initializing I2C Master to SMCLK at 100kbs with autostop */
            MAP_I2C_initMaster(EUSCI_B3_BASE, &i2cConfig_B3);
        }
    }
    
    /***********************************************************
      Function:
    
      @param module the EUSCI module to use ex: EUSCI_B0_BASE
      @param ui8Addr the 7 bit address of the module
      @param ui8Reg the register to write to
      @param Data a pointer to where the data to be written is stored
      @param ui32ByteCount the number of bytes to write
      @returns true if successful, false otherwise
    */
    bool writeI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
    {
        /* Wait until ready to write */
        while (MAP_I2C_isBusBusy(module));
    
        /* Assign Data to local Pointer */
        pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(module);
    
        /* Setup the number of bytes to transmit + 1 to account for the register byte */
        if(module == EUSCI_B0_BASE){
            i2cConfig_B0.byteCounterThreshold = ui8ByteCount + 1;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0);
        }else if(module == EUSCI_B1_BASE){
            i2cConfig_B1.byteCounterThreshold = ui8ByteCount + 1;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1);
        }else if(module == EUSCI_B2_BASE){
            i2cConfig_B2.byteCounterThreshold = ui8ByteCount + 1;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2);
        }else if(module == EUSCI_B3_BASE){
            i2cConfig_B3.byteCounterThreshold = ui8ByteCount + 1;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3);
        }else{
            return false;
        }
    
    
        /* Load device slave address */
        MAP_I2C_setSlaveAddress(module, ui8Addr);
    
        /* Enable I2C Module to start operations */
        MAP_I2C_enableModule(module);
    
        /* Enable master STOP, TX and NACK interrupts */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
        /* Set our local state to Busy */
        ui8Status = eUSCI_BUSY;
    
        /* Send start bit and register */
        MAP_I2C_masterSendMultiByteStart(module,ui8Reg);
    
        /* Enable master interrupt for the remaining data */
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        // NOW WAIT FOR DATA BYTES TO BE SENT
        while(ui8Status == eUSCI_BUSY)
        {
    #ifdef USE_LPM
            MAP_PCM_gotoLPM0();
    #else
            __no_operation();
    #endif
        }
    
        /* Disable interrupts */
        MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        if(ui8Status == eUSCI_NACK)
        {
            return(false);
        }
        else
        {
            return(true);
        }
    }
    
    /***********************************************************
      Function:
    
      @param module the EUSCI module to use ex: EUSCI_B0_BASE
      @param ui8Addr the 7 bit address of the module
      @param ui8Reg the register to read from
      @param Data a pointer to where to put the data
      @param ui32ByteCount the number of bytes to read
      @returns true if successful, false otherwise
    */
    bool readI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
    {
        /* Todo: Put a delay */
        //todo reset if busy for long enough time
        /* Wait until ready */
        while (MAP_I2C_isBusBusy(module));
    
        /* Assign Data to local Pointer */
        pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(module);
    
        /* Setup the number of bytes to receive */
        if(module == EUSCI_B0_BASE){
            i2cConfig_B0.byteCounterThreshold = ui8ByteCount;
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0);
        }else if(module == EUSCI_B1_BASE){
            i2cConfig_B1.byteCounterThreshold = ui8ByteCount;
            i2cConfig_B1.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1);
        }else if(module == EUSCI_B2_BASE){
            i2cConfig_B2.byteCounterThreshold = ui8ByteCount;
            i2cConfig_B2.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2);
        }else if(module == EUSCI_B3_BASE){
            i2cConfig_B3.byteCounterThreshold = ui8ByteCount;
            i2cConfig_B3.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3);
        }else{
            return false;
        }
    
        /* Load device slave address */
        MAP_I2C_setSlaveAddress(module, ui8Addr);
    
        /* Enable I2C Module to start operations */
        MAP_I2C_enableModule(module);
    
        /* Enable master STOP and NACK interrupts */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT);
    
        /* Set our local state to Busy */
        ui8Status = eUSCI_BUSY;
    
        /* Send start bit and register */
        MAP_I2C_masterSendMultiByteStart(module,ui8Reg);
    
        /* Enable master interrupt for the remaining data */
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        /* NOTE: If the number of bytes to receive = 1, then as target register is being shifted
         * out during the write phase, UCBxTBCNT will be counted and will trigger STOP bit prematurely
         * If count is > 1, wait for the next TXBUF empty interrupt (just after reg value has been
         * shifted out
         *
         * If your code is getting stuck here, you probably called this function from an interrupt
         * DON'T DO THAT!
         */
        while(ui8Status == eUSCI_BUSY)
        {
            if(MAP_I2C_getInterruptStatus(module, EUSCI_B_I2C_TRANSMIT_INTERRUPT0))
            {
                ui8Status = eUSCI_IDLE;
            }
        }
    
        ui8Status = eUSCI_BUSY;
    
        /* Turn off TX and generate RE-Start */
        MAP_I2C_masterReceiveStart(module);
    
        /* Enable RX interrupt */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    
        /* Wait for all data be received */
        while(ui8Status == eUSCI_BUSY)
        {
    
    #ifdef USE_LPM
            MAP_PCM_gotoLPM0();
    #else
            __no_operation();
    #endif
        }
    
        /* Disable interrupts */
        MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        if(ui8Status == eUSCI_NACK)
        {
            return(false);
        }
        else
        {
            return(true);
        }
    }
    
    /***********************************************************
      Function:
      @param module the EUSCI module to use ex: EUSCI_B0_BASE
      @param ui8Addr the 7 bit address of the module
      @param ui8Reg the register to read from
      @param Data a pointer to where to put the data
      @param ui32ByteCount the number of bytes to read
      @returns true if successful, false otherwise
    */
    bool readBurstI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint32_t ui32ByteCount)
    {
        /* Todo: Put a delay */
        /* Wait until ready */
        while (MAP_I2C_isBusBusy(module));
    
        /* Assign Data to local Pointer */
        pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(module);
    
        /* Setup the number of bytes to receive */
        if(module == EUSCI_B0_BASE){
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
            g_ui32ByteCount = ui32ByteCount;
            burstMode = true;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0);
        }else if(module == EUSCI_B1_BASE){
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
            g_ui32ByteCount = ui32ByteCount;
            burstMode = true;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1);
        }else if(module == EUSCI_B2_BASE){
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
            g_ui32ByteCount = ui32ByteCount;
            burstMode = true;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2);
        }else if(module == EUSCI_B3_BASE){
            i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
            g_ui32ByteCount = ui32ByteCount;
            burstMode = true;
            MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3);
        }else{
            return false;
        }
    
    
        /* Load device slave address */
        MAP_I2C_setSlaveAddress(module, ui8Addr);
    
        /* Enable I2C Module to start operations */
        MAP_I2C_enableModule(module);
    
        /* Enable master STOP and NACK interrupts */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT);
    
        /* Set our local state to Busy */
        ui8Status = eUSCI_BUSY;
    
        /* Send start bit and register */
        MAP_I2C_masterSendMultiByteStart(module,ui8Reg);
    
        /* Enable master interrupt for the remaining data */
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_enableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
        /* NOTE: If the number of bytes to receive = 1, then as target register is being shifted
         * out during the write phase, UCBxTBCNT will be counted and will trigger STOP bit prematurely
         * If count is > 1, wait for the next TXBUF empty interrupt (just after reg value has been
         * shifted out
         *
         * If your code is getting stuck here, you probably called this function from an interrupt
         * DON'T DO THAT!
         */
        while(ui8Status == eUSCI_BUSY)
        {
            if(MAP_I2C_getInterruptStatus(module, EUSCI_B_I2C_TRANSMIT_INTERRUPT0))
            {
                ui8Status = eUSCI_IDLE;
            }
        }
    
        ui8Status = eUSCI_BUSY;
    
        /* Turn off TX and generate RE-Start */
        MAP_I2C_masterReceiveStart(module);
    
        /* Enable RX interrupt */
        MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    
        /* Wait for all data be received */
        while(ui8Status == eUSCI_BUSY)
        {
    
    #ifdef USE_LPM
            MAP_PCM_gotoLPM0();
    #else
            __no_operation();
    #endif
        }
    
        /* Disable interrupts */
        MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT +
                EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    
        if(module == EUSCI_B0_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB0);
        }else if(module == EUSCI_B1_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
        }else if(module == EUSCI_B2_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB2);
        }else if(module == EUSCI_B3_BASE){
            MAP_Interrupt_disableInterrupt(INT_EUSCIB3);
        }else{
            return false;
        }
    
    
        if(ui8Status == eUSCI_NACK)
        {
            return(false);
        }
        else
        {
            return(true);
        }
    }
    
    /***********************************************************
      Function: euscib0IntHandler
     */
    void eusciB0IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_BASE);
        MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
            /* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
    
            /* Clear any pending TX interrupts */
            MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
            /* Set our local state to NACK received */
            ui8Status = eUSCI_NACK;
        }
    
        if (status & EUSCI_B_I2C_START_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_START;
        }
    
        if (status & EUSCI_B_I2C_STOP_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_STOP;
        }
    
        if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
        {
            /* RX data */
            *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
            ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
    
            if (burstMode)
            {
                g_ui32ByteCount--;
                if (g_ui32ByteCount == 1)
                {
                    burstMode = false;
    
                    /* Generate STOP */
                    MAP_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
                }
            }
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
            /* Send the next data */
            MAP_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    void eusciB1IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B1_BASE);
        MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
            /* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);
    
            /* Clear any pending TX interrupts */
            MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
            /* Set our local state to NACK received */
            ui8Status = eUSCI_NACK;
        }
    
        if (status & EUSCI_B_I2C_START_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_START;
        }
    
        if (status & EUSCI_B_I2C_STOP_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_STOP;
        }
    
        if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
        {
            /* RX data */
            *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
            ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE);
    
            if (burstMode)
            {
                g_ui32ByteCount--;
                if (g_ui32ByteCount == 1)
                {
                    burstMode = false;
    
                    /* Generate STOP */
                    MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE);
                }
            }
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
            /* Send the next data */
            MAP_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    void eusciB2IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B2_BASE);
        MAP_I2C_clearInterruptFlag(EUSCI_B2_BASE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
            /* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B2_BASE);
    
            /* Clear any pending TX interrupts */
            MAP_I2C_clearInterruptFlag(EUSCI_B2_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
            /* Set our local state to NACK received */
            ui8Status = eUSCI_NACK;
        }
    
        if (status & EUSCI_B_I2C_START_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_START;
        }
    
        if (status & EUSCI_B_I2C_STOP_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_STOP;
        }
    
        if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
        {
            /* RX data */
            *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE);
            ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE);
    
            if (burstMode)
            {
                g_ui32ByteCount--;
                if (g_ui32ByteCount == 1)
                {
                    burstMode = false;
    
                    /* Generate STOP */
                    MAP_I2C_masterSendMultiByteStop(EUSCI_B2_BASE);
                }
            }
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
            /* Send the next data */
            MAP_I2C_masterSendMultiByteNext(EUSCI_B2_BASE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    void eusciB3IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B3_BASE);
        MAP_I2C_clearInterruptFlag(EUSCI_B3_BASE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
            /* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B3_BASE);
    
            /* Clear any pending TX interrupts */
            MAP_I2C_clearInterruptFlag(EUSCI_B3_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    
            /* Set our local state to NACK received */
            ui8Status = eUSCI_NACK;
        }
    
        if (status & EUSCI_B_I2C_START_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_START;
        }
    
        if (status & EUSCI_B_I2C_STOP_INTERRUPT)
        {
            /* Change our local state */
            ui8Status = eUSCI_STOP;
        }
    
        if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0)
        {
            /* RX data */
            *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B3_BASE);
            ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B3_BASE);
    
            if (burstMode)
            {
                g_ui32ByteCount--;
                if (g_ui32ByteCount == 1)
                {
                    burstMode = false;
    
                    /* Generate STOP */
                    MAP_I2C_masterSendMultiByteStop(EUSCI_B3_BASE);
                }
            }
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
            /* Send the next data */
            MAP_I2C_masterSendMultiByteNext(EUSCI_B3_BASE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    

    4666.i2c_driver.h

**Attention** This is a public forum