This thread has been locked.

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

MSP432P401R I2C mode not working



Hello,

I tried set up an eusci module in i2c mode but with no luck.

The driverlib examples and the ones for the device do not work. I hooked up an logic analyzer on the pins but they stay high all the time.

Have any of you got it up and running ?

Andrei 

  • Hi Andrei,

    Just to make sure, are the pull up resistors present and correctly configured on the module?

    Sincerely,
    Sean
  • Hi Sean,

    I connected an Atmel transceiver to the MSP432 launchpad. The transceiver module has an I2C EEPROM module to store the EUI64 address and already has the SDA and SCL line pulled up using 10k resistors.

    I've tried using eusci0 and eusci1. The same problem. I don't even see the start condition on the logic analyzer, the signals remain high.

    Andrei
  • Hi Andrei,

    Sorry for the extremely late response, I've overlooked this thread. Are you still having an issue with the Atmel transceiver?

    Sincerely,
    Sean
  • Hi Sean,

    Yes, still no luck.

    Andrei

  • Hey Andrei,

    What driverlib examples for I2C did you use to communicate with the Atmel transceiver? The code needs to be modified as the examples are not set up for the Atmel transceiver specifically.

    Sincerely,
    Sean
  • Hi Sean,

    First I used directly the registers, doing the configuration myself. Next I tried using the driverlib examples.

    Both cases rise up the same issue: the code get stuck waiting for the UCTXIFG flag after sending the start condition by setting the UCTR and the UCTXSTT bits in the UCxCTLW0 register.

    I checked the UCTXSTT bit, which by the reference manual, should be cleared after successfully sending of the start condition.

    Using a logic analyzer, I can confirm that the start condition is never sent.

    Thanks,

    Andrei  

  • Hey Andrei,

    Could you attach the code for setting up the I2C? Also, what is the Atmel transceiver part number and the master-slave configuration?

    Sincerely,
    Sean

  • Please find attached the i2c code. The i2c configuration function is called in HAL_I2C_Init().

    I want to use i2c to get the pre-programmed MAC address in the eeprom located in the AT86RF233 module.

    For this, I plan to use the MAC_ReadEUI64() function. The module part number is ATZB-RF-233-1-C, and the i2c memory is AT24MAC402.

    i2c.zip

  • Hi Andrei,

    I'm still running through your code, in the meantime, I did find out that the default driverlib I2C repeated start master code seems to have an issue. I've asked around and found a version of the code that works, attached is the code and let me know if you can configure it to communicate with the Atmel part.

    Sincerely,

    Sean

    i2c_driver.h

    //*****************************************************************************
    //
    // 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.
    //
    //****************************************************************************
    #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;
    
    /* I2C Master Configuration Parameter */
    #if 0
    volatile eUSCI_I2C_MasterConfig i2cConfig =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
    		0,
    		EUSCI_B_I2C_SET_DATA_RATE_400KBPS,      // Desired I2C Clock of 400khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    #else
    volatile eUSCI_I2C_MasterConfig i2cConfig =
    {
            EUSCI_B_I2C_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
    		0,
    		100000,                                  // Desired I2C Clock of 20khz
            0,                                      // No byte counter threshold
            EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD                // Autostop
    };
    #endif
    //*****************************************************************************
    //
    // Imported Data
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Constants
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // Function Prototypes
    //
    //*****************************************************************************
    
    /***********************************************************
      Function:
    */
    void initI2C(void)
    {
    	/* I2C Clock Soruce Speed */
    	i2cConfig.i2cClk = MAP_CS_getSMCLK();
    
        /* Select I2C function for I2C_SCL(P6.5) & I2C_SDA(P6.4) */
        GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN5 | GPIO_PIN4,
                GPIO_PRIMARY_MODULE_FUNCTION);
    
        /* Initializing I2C Master to SMCLK at 400kbs with autostop */
    //    MAP_I2C_initMaster(EUSCI_B1_MODULE, &i2cConfig);
    }
    
    /***********************************************************
      Function:
    */
    bool writeI2C(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
    {
    	/* Wait until ready to write */
        while (MAP_I2C_isBusBusy(EUSCI_B1_BASE));
    
    	/* Assign Data to local Pointer */
    	pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(EUSCI_B1_MODULE);
    
    	/* Setup the number of bytes to transmit + 1 to account for the register byte */
        i2cConfig.byteCounterThreshold = ui8ByteCount + 1;
        MAP_I2C_initMaster(EUSCI_B1_MODULE, (const eUSCI_I2C_MasterConfig *)&i2cConfig);
    
    	/* Load device slave address */
    	MAP_I2C_setSlaveAddress(EUSCI_B1_MODULE, ui8Addr);
    
        /* Enable I2C Module to start operations */
    	MAP_I2C_enableModule(EUSCI_B1_MODULE);
    
      	/* Enable master STOP, TX and NACK interrupts */
        MAP_I2C_enableInterrupt(EUSCI_B1_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(EUSCI_B1_MODULE,ui8Reg);
    
      	/* Enable master interrupt for the remaining data */
        MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
    
    	// 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(EUSCI_B1_MODULE, EUSCI_B_I2C_STOP_INTERRUPT +
    			EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
        MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
    
    	if(ui8Status == eUSCI_NACK)
    	{
    		return(false);
    	}
    	else
    	{
    		return(true);
    	}
    }
    
    /***********************************************************
      Function:
    */
    bool readI2C(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
    {
    	/* Todo: Put a delay */
    	/* Wait until ready */
        while (MAP_I2C_isBusBusy(EUSCI_B1_BASE));
    
    	/* Assign Data to local Pointer */
    	pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(EUSCI_B1_MODULE);
    
      	/* Setup the number of bytes to receive */
        i2cConfig.byteCounterThreshold = ui8ByteCount;
        i2cConfig.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;
        MAP_I2C_initMaster(EUSCI_B1_MODULE, (const eUSCI_I2C_MasterConfig *)&i2cConfig);
    
    	/* Load device slave address */
    	MAP_I2C_setSlaveAddress(EUSCI_B1_MODULE, ui8Addr);
    
        /* Enable I2C Module to start operations */
    	MAP_I2C_enableModule(EUSCI_B1_MODULE);
    
      	/* Enable master STOP and NACK interrupts */
        MAP_I2C_enableInterrupt(EUSCI_B1_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(EUSCI_B1_MODULE,ui8Reg);
    
      	/* Enable master interrupt for the remaining data */
        MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
    
      	/* 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
      	 */
    	while(ui8Status == eUSCI_BUSY)
    	{
    		if(MAP_I2C_getInterruptStatus(EUSCI_B1_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0))
    		{
    			ui8Status = eUSCI_IDLE;
    		}
    	}
    
    	ui8Status = eUSCI_BUSY;
    
      	/* Turn off TX and generate RE-Start */
      	MAP_I2C_masterReceiveStart(EUSCI_B1_MODULE);
    
      	/* Enable RX interrupt */
        MAP_I2C_enableInterrupt(EUSCI_B1_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(EUSCI_B1_MODULE, EUSCI_B_I2C_STOP_INTERRUPT +
    			EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
        MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
    
    	if(ui8Status == eUSCI_NACK)
    	{
    		return(false);
    	}
    	else
    	{
    		return(true);
    	}
    }
    
    /***********************************************************
      Function:
    */
    bool readBurstI2C(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint32_t ui32ByteCount)
    {
    	/* Todo: Put a delay */
    	/* Wait until ready */
        while (MAP_I2C_isBusBusy(EUSCI_B1_BASE));
    
    	/* Assign Data to local Pointer */
    	pData = Data;
    
        /* Disable I2C module to make changes */
        MAP_I2C_disableModule(EUSCI_B1_MODULE);
    
      	/* Setup the number of bytes to receive */
        i2cConfig.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;
        g_ui32ByteCount = ui32ByteCount;
        burstMode = true;
        MAP_I2C_initMaster(EUSCI_B1_MODULE, (const eUSCI_I2C_MasterConfig *)&i2cConfig);
    
    	/* Load device slave address */
    	MAP_I2C_setSlaveAddress(EUSCI_B1_MODULE, ui8Addr);
    
        /* Enable I2C Module to start operations */
    	MAP_I2C_enableModule(EUSCI_B1_MODULE);
    
      	/* Enable master STOP and NACK interrupts */
        MAP_I2C_enableInterrupt(EUSCI_B1_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(EUSCI_B1_MODULE,ui8Reg);
    
      	/* Enable master interrupt for the remaining data */
        MAP_Interrupt_enableInterrupt(INT_EUSCIB1);
    
      	/* 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
      	 */
    	while(ui8Status == eUSCI_BUSY)
    	{
    		if(MAP_I2C_getInterruptStatus(EUSCI_B1_MODULE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0))
    		{
    			ui8Status = eUSCI_IDLE;
    		}
    	}
    
    	ui8Status = eUSCI_BUSY;
    
      	/* Turn off TX and generate RE-Start */
      	MAP_I2C_masterReceiveStart(EUSCI_B1_MODULE);
    
      	/* Enable RX interrupt */
        MAP_I2C_enableInterrupt(EUSCI_B1_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(EUSCI_B1_MODULE, EUSCI_B_I2C_STOP_INTERRUPT +
    			EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
        MAP_Interrupt_disableInterrupt(INT_EUSCIB1);
    
    	if(ui8Status == eUSCI_NACK)
    	{
    		return(false);
    	}
    	else
    	{
    		return(true);
    	}
    }
    
    /***********************************************************
      Function: euscib1IntHandler
     */
    void euscib1IntHandler(void)
    {
        uint_fast16_t status;
    
        status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B1_MODULE);
        MAP_I2C_clearInterruptFlag(EUSCI_B1_MODULE, status);
    
        if (status & EUSCI_B_I2C_NAK_INTERRUPT)
        {
        	/* Generate STOP when slave NACKS */
            MAP_I2C_masterSendMultiByteStop(EUSCI_B1_MODULE);
    
        	/* Clear any pending TX interrupts */
        	MAP_I2C_clearInterruptFlag(EUSCI_B1_MODULE, 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_MODULE);
        	ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_MODULE);
    
        	if (burstMode)
        	{
        		g_ui32ByteCount--;
        		if (g_ui32ByteCount == 1)
        		{
        			burstMode = false;
    
        			/* Generate STOP */
        	        MAP_I2C_masterSendMultiByteStop(EUSCI_B1_MODULE);
        		}
        	}
        }
    
        if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0)
        {
        	/* Send the next data */
        	MAP_I2C_masterSendMultiByteNext(EUSCI_B1_MODULE, *pData++);
        }
    
    #ifdef USE_LPM
        MAP_Interrupt_disableSleepOnIsrExit();
    #endif
    }
    
    

  • Hi Sean,

    It looks like the code you provided works, I can see a start condition and some data being sent.
    What was the driverlib issue ?

    I will browse my code to see what am I doing wrong.

    Regards,
    Andrei
  • Hi Andrei,

    Glad to know that the code is working, I've contacted someone from the MSP432 driverlib team to further look into the example code.

    Sincerely,
    Sean
  • Hello Andrei,

    Could you tell me the following information?

    • Which version of MSP432 DriverLib are you using? There should be a version stamp on top of the DriverLib examples or header/source files with this information.
    • Which IDE are you using (CCS/Keil/IAR/etc.)
    • Which version of MSP432 are you using? On the actual chip, under the part number, there should be a RevA or RevB on the chip.

    I have tested the stock i2c_master_rw_repeated_start-master_code and i2c_master_rw_repeated_start-slave_code code examples using Code Composer Studio 6.1.0  and cannot recreate your problem. Hooking up a logic analyzer to the line, I get the following signals:

    ... which is the expected output from the code examples. I am using the latest MSP432 DriverLib (2_20_00_08) on the web at:

    Thanks for bringing this up though as if there is an issue we definitely do want to resolve it.

    Best Regards,
    Tim

  • Hi Tim,

    I managed to find what the problem was. For some reason, I was not configuring the GPIO pins properly. Everything works now.
    In my project, I'm not using driverlib at all. The configuration is done by writing directly to the registers.

    Thanks for your help.

    Regards,
    Andrei

**Attention** This is a public forum